Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net 2+: why does if( 1 == null ) no longer throw a compiler exception?

I'm using int as an example, but this applies to any value type in .Net

In .Net 1 the following would throw a compiler exception:

int i = SomeFunctionThatReturnsInt();

if( i == null ) //compiler exception here

Now (in .Net 2 or 3.5) that exception has gone.

I know why this is:

int? j = null; //nullable int

if( i == j )   //this shouldn't throw an exception

The problem is that because int? is nullable and int now has a implicit cast to int?. The syntax above is compiler magic. Really we're doing:

Nullable<int> j = null; //nullable int

//compiler is smart enough to do this
if( (Nullable<int>) i == j)   

//and not this
if( i == (int) j)

So now, when we do i == null we get:

if( (Nullable<int>) i == null )

Given that C# is doing compiler logic to calculate this anyway why can't it be smart enough to not do it when dealing with absolute values like null?

like image 509
Keith Avatar asked Sep 15 '08 13:09

Keith


3 Answers

I don't think this is a compiler problem per se; an integer value is never null, but the idea of equating them isn't invalid; it's a valid function that always returns false. And the compiler knows; the code

bool oneIsNull = 1 == null;

compiles, but gives a compiler warning: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'.

So if you want the compiler error back, go to the project properties and turn on 'treat warnings as errors' for this error, and you'll start seeing them as build-breaking problems again.

like image 194
Steve Cooper Avatar answered Oct 21 '22 23:10

Steve Cooper


Odd ... compiling this with VS2008, targetting .NET 3.5:

static int F()
{
    return 42;
}

static void Main(string[] args)
{
    int i = F();

    if (i == null)
    {
    }
}

I get a compiler warning

warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'

And it generates the following IL ... which presumably the JIT will optimize away

L_0001: call int32 ConsoleApplication1.Program::F()
L_0006: stloc.0 
L_0007: ldc.i4.0 
L_0008: ldc.i4.0 
L_0009: ceq 
L_000b: stloc.1 
L_000c: br.s L_000e

Can you post a code snippet?

like image 24
Rob Walker Avatar answered Oct 21 '22 23:10

Rob Walker


Compiler still generates warning when you compare non-nullable type to null, which is just the way it should be. May be your warning level is too low or this was changed in recent versions (I only did that in .net 3.5).

like image 1
ima Avatar answered Oct 21 '22 23:10

ima