Why is there a difference in checking null against a value in VB.NET and C#?

.net-4.0, c#, null, vb.net

Solution

VB.NET and C#.NET are different languages, built by different teams who have made different assumptions about usage; in this case the semantics of a NULL comparison.

My personal preference is for the VB.NET semantics, which in essence gives NULL the semantics "I don't know yet". Then the comparison of 5 to "I don't know yet". is naturally "I don't know yet"; ie NULL. This has the additional advantage of mirroring the behaviour of NULL in (most if not all) SQL databases. This is also a more standard (than C#'s) interpretation of three-valued logic, as explained here.

The C# team made different assumptions about what NULL means, resulting in the behaviour difference you show. Eric Lippert wrote a blog about the meaning of NULL in C#. Per Eric Lippert: "I also wrote about the semantics of nulls in VB / VBScript and JScript here and here".

In any environment in which NULL values are possible, it is imprtant to recognize that the Law of the Excluded Middle (ie that A or ~A is tautologically true) no longer can be relied on.

Update:

A `bool` (as opposed to a `bool?`) can only take the values TRUE and FALSE. However a language implementation of NULL must decide on how NULL propagates through expressions. In VB the expressions `5=null` and `5<>null` BOTH return false. In C#, of the comparable expressions `5==null` and `5!=null` only the second first [updated 2014-03-02 - PG] returns false. However, in ANY environment that supports null, it is incumbent on the programmer to know the truth tables and null-propagation used by that language.

Update

Eric Lippert's blog articles (mentioned in his comments below) on semantics are now at:

Sep. 30, 2003 - A Whole Lot of Nothing

Oct. 1, 2003 - A Little More on Nothing

Problem

In VB.NET this happens: ``` Dim x As System.Nullable(Of Decimal) = Nothing Dim y As System.Nullable(Of Decimal) = Nothing y = 5 If x <> y Then Console.WriteLine("true") Else Console.WriteLine("false") '' <-- I got this. Why? End If ``` But in C# this happens: ``` decimal? x = default(decimal?); decimal? y = default(decimal?); y = 5; if (x != y) { Debug.WriteLine("true"); // <-- I got this -- I'm with you, C# :) } else { Debug.WriteLine("false"); } ``` Why is there a difference?

Original source

Related problems