I was just reading about a post on nulls by Sharon Bjeletich, which reminded me of an observation that I made last month. The C# 3.0 and VB 9.0 are diverging once again—this time in their treatment of null comparison.
In C# 3.0, nullable value types are analogous to reference types. In VB 9.0, nullable values types conform to SQL behavior.
|Underlying philosophy||Nullable types bridge the discontinuity between value and reference types, where nulls represent nonexistent values.||Nullable values conform to SQL behavior, in which nulls represent unknown values.|
Equality operations(==, !=)
|Equality operations between two nullable values result in values of type Boolean.||Equality operations between two nullable values result in values of type Nullable<Boolean>.|
|Equality of nulls||Two null values return true, while the presence of only one null returns false.||The presence of one or more null values in an equality returns a null value.|
|Comparisons between two nullable values result in values of type Boolean.||Comparisons between two nullable values result in values of type Nullable<Boolean>.|
Comparison of nulls
|The presence of a null value causes the comparison to return false.||The presence of a null value causes the comparison to return null.|
Which is better? Well, each approach introduces its own advantages and disadvantages. The problem lies in that the programming world and the database world evolved separate interpretations of null values, neither of which is necessarily superior to the other; each interpretation is better suited to its domain. C# has just chosen an object perspective, while VB has chosen a data perspective.
C#’s approach provides more consistency with reference types (although, not complete consistency, since reference equality is still not possible with nullable value types). For example, equality operations in C# work exactly the same regardless of whether the values are boxed or not.
In VB, the equality operator may work differently for nullable types in different contexts, mainly due to the nullbox DCR, because VB has no way of knowing whether a null object is a boxed null value. This problem is acute when explicit typing is turned off. VB defines a special syntax to alleviate this problem such as a nullable object type ( Object? ) and a postfix ? modifier to variables to signal when objects should observe SQL nullable semantics. I do foresee problems with generic methods and types.
I should note that VB has two different equality operators, = and Is, to test separately for equivalency and identity. I don’t know if VB will allow Is to be use between nullable values in the same manner as C#’s equality operators.
Unlike C#, VB’s approach does provide consistency across arithmetic operations, equality operations, and comparison operations. C#’s equality and comparison operations are inconsistent with each other and with all the other operations. Notably, null == null returns true, whereas null >= null returns false, breaking the invariant that x >= y is equivalent to x > y or x = y.
VB also provides greater consistency with databases. C#’s approach might present problems within query expressions against DLINQ, because the same expression in a where clause can have competing interpretations.