The problem that's observed here is a special case of a more general problem, which is that the number of different definitions of equality that may be useful in at least some circumstances exceeds the number of commonly-available means to express them. This problem is in some cases made worse by an unfortunate belief that it is confusing to have different means of testing equality yield different results, and such confusion might be avoided by having the different forms of equality yield the same results whenever possible.
In reality, the fundamental cause of confusion is a misguided belief that the different forms of equality and inequality testing should be expected to yield the same result, notwithstanding the fact that different semantics are useful in different circumstances. For example, from an arithmetic standpoint, it's useful to be able to have Decimal
which differ only in the number of trailing zeroes compare as equal. Likewise for double
values like positive zero and negative zero. On the other hand, from a caching or interning standpoint, such semantics can be deadly. Suppose, for example, one had a Dictionary<Decimal, String>
such that myDict[someDecimal]
should equal someDecimal.ToString()
. Such an object would seem reasonable if one had many Decimal
values that one wanted to convert to string and expected there to be many duplicates. Unfortunately, if used such caching to convert 12.3 m and 12.40 m, followed by 12.30 m and 12.4 m, the latter values would yield "12.3", and "12.40" instead of "12.30" and "12.4".
Returning to the matter at hand, there is more than one sensible way of comparing nullable objects for equality. C# takes the standpoint that its ==
operator should mirror the behavior of Equals
. VB.NET takes the standpoint that its behavior should mirror that of some other languages, since anyone who wants the Equals
behavior could use Equals
. In some sense, the right solution would be to have a three-way "if" construct, and require that if the conditional expression returns a three-valued result, code must specify what should happen in the null
case. Since that is not an option with languages as they are, the next best alternative is to simply learn how different languages work and recognize that they are not the same.
Incidentally, Visual Basic's "Is" operator, which is lacking in C, can be used to test for whether a nullable object is, in fact, null. While one might reasonably question whether an if
test should accept a Boolean?
, having the normal comparison operators return Boolean?
rather than Boolean
when invoked on nullable types is a useful feature. Incidentally, in VB.NET, if one attempts to use the equality operator rather than Is
, one will get a warning that the result of the comparison will always be Nothing
, and one should use Is
if one wants to test if something is null.
default(decimal?)
is returning 0, notnull
. – Colonnull
– Khasi0 != 5
just asnull != 5
, right? – HeretoIf
conditionals do not require to evaluate as a boolean... uuuugh EDIT: SoNothing <> Anything = Nothing
which results in theIf
taking the negative/else route. – Hereto