Why "long value" equals to null is allowed?
.net, c#
Solution
As @Tim pointed out, you won't get an error for the following code:
long foo = 42;
if (foo == null) { }
You'll get a warning instead:
The result of the expression is always 'false' since a value of type 'long' is never equal to 'null' of type 'long?'.
This gives a warning instead of an error because of lifted operators, defined in the C# language specification as such:
Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. [...] For the equality operators
== !=
a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. The lifted form is constructed by adding a single ? modifier to each operand type. The lifted operator considers two null values equal, and a null value unequal to any non-null value. If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.
The "underlying operator" in this case is the predefined value type `long`'s `==` operator:
For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise.
Because `foo` is implicitly converted ("Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types.") and the `null` literal is also implicitly converted ("An implicit conversion exists from the null literal to any nullable type."), the expression:
(long)foo == null
Becomes:
(long?)foo == (long?)null
Which, given `foo` is of type `long` and thus always has a value, always returns false and won't even apply `long`'s `==` operator.
I'm not entirely sure, but I suspect this to exist to enable comparison between nullable and non-nullable values without explicit casting:
long? foo = 42;
long bar = 42;
Console.WriteLine(foo == bar); // true
foo = null;
Console.WriteLine(bar == foo); // false
If this wasn't handled by the language as specified above, you'd get "Operator `==` cannot be applied to operands of type `long?` and `long`", because `Nullable<T>` doesn't have an `==` operator, and `long` doesn't have an `==` operator accepting a `long?`.
Problem
When I was debugging a few lines of code and asking me why on earth it wasn't working I have stumbled on this situation ... ``` if(answer.AnswerID == null) { // do something } ``` When in fact it should be this way: ``` if(answer == null) { // do something } ``` - `answer` is an object of the type `Answer - a class`. - `AnswerID` is a property of type `long`. The weird thing is that if you try something like this: ``` long myLongValue = null; ``` The compiler will show you an error: ``` Connot convert null to long ... ``` So my question is: Why did I not get a compile error when I was trying to compare a `long type` with `null`? EDITED This question IS NOT about `nullable` types. I'm asking WHY .NET allows me to compare a long variable with null. I'm talking about `long type` and not about `long? type`.