Tutorial :Why nullable types will not be equal in this case?



Question:

Surprisingly the code bellow will not succeed.

int? n1 = null;  int? n2 = null;  Assert.IsTrue(n1 <= n2);  // Fails here  

Do you know why?


Solution:1

Using boolean logic with null nullable values in C# (and VB.Net) often times defies logic. I find the best way to make sense of it is to remember that "null is not a value". Because null is not a value you cannot do any operations on it. Hence things like "1 > null" and "1 < null" are both true.

Here is a detailed guide: http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx

If you do want to treat null as a value then you could use the GetValueOrDefaultMethod() to equate null with the default value. For example

Assert.IsTrue(n1.GetValueOrDefault() <= n2.GetValueOrDefault());  // True  

This is a bit verbose but it will get the job done.


Solution:2

Either this is a typo and you meant "==" not "<=" or you misunderstand how nulls work.

In almost all languages (including c#) the only default legal operation on null is to check if something else is equal to it (in .Net == is by default reference equality).

<= and >= are not meaningful (as they would have very strange behaviour if they did)

Some languages (SQL being possibly the most well known) disallow the use of 'standard' equality operators to make this even more clear. in SQL null == null is NOT true, and a compliant server will refuse queries where you attempt to do this via a literal.

C# takes the same route as it's heritage (C style imperative languages) where the test for a null value is based on testing that the bits in it are zero (things get somewhat more complex but fundamentally that's what is happening). As such only reference types can truly be null (Nullable<T> has a lot of magic behind the scenes to make it look like it is but actually under the hood it isn't null). This means that the reference equality semantics follow nicely into null semantics, thus the == null is allowed.

Other languages implement null in a different fashion (for example SQL where anything can be made null thus the 'nullness' of something must be stored outside of it (much like Nullable). This means that the conventional use of equality need not be the primary concern and null can be truly special rather than a special case of certain types. For further information on the specialness of null take a look at This question has a list of such languages

Most reference types do not define a >= or <= operator so there is little problem in practice with the disconnect between == and <= (where normally if something is true for == it would be true for <= and >= as well).


Solution:3

You can try this:

int? n1 = null;  int? n2 = null;    // Test for equality  Assert.IsTrue((n1.HasValue && n2.HasValue && n1.Value == n2.Value) || (!n1.HasValue && !n2.HasValue));    // Test for less than or equal to  Assert.IsTrue(n1.HasValue && n2.HasValue && n1.Value <= n2.Value);  


Solution:4

Nullable types are wrapped into a System.Nullable object, so you don't compare the int value, you compare the reference. To compare the values, you need to make it like that:

Assert.IsTrue(n1.Value <= n2.Value);  

I wrote a bit about nullable on my blog.

Edit: But in your case n1 and n2 is null, so you can't even compare the values.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »