C# okay with comparing value types to null
This is legal because operator overload resolution has a unique best operator to choose. There is an == operator that takes two nullable ints. The int local is convertible to a nullable int. The null literal is convertible to a nullable int. Therefore this is a legal usage of the == operator, and will always result in false.
Similarly, we also allow you to say "if (x == 12.6)", which will also always be false. The int local is convertible to a double, the literal is convertible to a double, and obviously they will never be equal.
Why can I compare an enum with null?
The enum is casted to a nullable version of it before comparison, so it can and will evaluate. The result is however always the same.
That is why the compiler warns you:
Warning CS0472 The result of the expression is always 'false' since a value of type 'Color' is never equal to 'null' of type 'Color?'
Although the comparison is useless, the compiler doesn't prevent you to perform it. Just like it doesn't prevent your to make a if(false) { }
, which is just as useless.
Why am I allowed to compare a non-nullable type with null?
The reason this works for DateTime
, is because DateTime
defines it own ==
operator. Because it does so, it gets a lifted version of the operator which may be used with DateTime?
. Since both DateTime
and null
may be implicitly converted to DateTime?
, the comparison compiles but will always evaluate to false at runtime.
Thanks to Matt Ellen for pointing out the fact that my original answer didn't cover the example in the question.
How do nullable types handle null values with comparison operators?
Does anyone have concrete information on how C# handles comparisons with Nullable types when one side of the comparison is null?
Yes - the C# language specification, section 7.3.7. In this case, it's a relational operator:
For the relation operators
< > <= >=
a lifted form of an operator exists if the operand types are both non-nullable types and if the result type isbool
. The lifted form is constructed by adding a single?
modifier to each operand type. The lifted operator produces the valuefalse
if one or both operands are null. Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce thebool
result.
There are similarly detailed sections for other operators.
When in doubt about how some aspect of the language works (and whether it's guaranteed or implementation-specific), the C# language specification should be your first port of call.
How does comparison operator works with null int?
According to MSDN - it's down the page in the "Operators" section:
When you perform comparisons with nullable types, if the value of one of the nullable types is
null
and the other is not, all comparisons evaluate tofalse
except for!=
So both a > b
and a < b
evaluate to false
since a
is null...
C# comparing reference and value types with null
In short, you can't compare like this, ever...
In regards to if (a.Right == b.Right == null)
It compiles because you can compare a non-nullable value types with null
and it's always false.
a.Right == b.Right // bool
bool == null //will be lifted and always equal false (see below)
To know the reason why you'll have to visit the specs and understand lifted operators
12.4.8 Lifted operators
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.
In regards to if(aa == bb == 0)
you can't compare bool
with an int
, there is no implicit conversion to bool
aa == bb // bool
bool == 0 // there is no implicit conversion to bool
Comparing 'int' to 'null' compiles
When the comparison is made, the compiler tries to make it so both operands of the comparison have compatible types if possible.
It had an int
value and a constant null
value (with no particular type). The only compatible type between the two values is int?
so they are coerced to int?
and compared as int? == int?
. Some int
value as an int?
is definitely non-null and null
is definitely null. The compiler realizes that and since a non-null value is not equal to a definite null
value, the warning is given.
Wrong compiler warning when comparing struct to null
You are correct: this is a bug in Visual Studio. The C# 4.0 standard (§ 7.3.7 Lifted operators) has this to say:
For the relational operators
< > <= >=
[…] The lifted operator produces the value
false
if one or both operands are null. …
And in fact, in MonoDevelop, you get the following warning instead:
The result of comparing type
System.DateTime
withnull
is alwaysfalse
.
How to compare an object to null in c#
Okay, the comment's giving it away:
Ok, in doing this, I noticed that when I hover over the variable in debugging mode, the value is null, but when it ISNT working, the value is {null}... What does {null} mean?
That suggest it's actually an array (or possibly another collection type) containing a single null reference, e.g.
object obj = new object[] { null };
The value of obj
is not a null reference, hence it doesn't go into the body of the if
statement.
How you should handle this depends on what you're trying to achieve. Do you really need obj
to be statically typed as just object
?
Why is comparing a struct to NULL legal in C#?
Fails to compile for me:
struct Foo { }
class Program
{
static void Main( string[] args )
{
var f = new Foo();
if( f == null ) { }
}
}
Error 1 Operator '==' cannot be applied to operands of type 'ConsoleApplication3.Foo' and 'null'
Related Topics
How to I Catch Ssl Exceptions in a Mono Httplistener Server
How to Turn a Datatable to a CSV
How to Read a File Even When Getting an "In Use by Another Process" Exception
C# Reflection: How to Get Class Reference from String
Specifying a Custom Datetime Format When Serializing with JSON.Net
Make First Letter of a String Upper Case (With Maximum Performance)
Generic Repository or Specific Repository for Each Entity
Convert Integers to Written Numbers
How to Protect My .Net Assemblies from Decompilation
Unauthorizedaccessexception Cannot Resolve Directory.Getfiles Failure
How to Create a Navigation Menu in Dotnet Application
Saving Any File to in the Database, Just Convert It to a Byte Array
Change Wpf Controls from a Non-Main Thread Using Dispatcher.Invoke
Split String Containing Command-Line Parameters into String[] in C#
Simplest Way to Do a Fire and Forget Method in C#