C# in Depth

Cover of C# in Depth
Order now (3rd edition)

Unexpected conversion

Chapter 4: Saying nothing with nullable types: 4.3.3

Created: 3/21/2008
Last updated: 3/21/2008

Ross Bradbury posted an interesting question on the C# in Depth Forum. It was sufficiently unexpected that we reckoned it was worth a note.

He had code which effectively looked like this (I've pared it down a little):

using System;

class Test
{
    public static implicit operator Test(int i)
    {
        Console.WriteLine("Converted from "+i);
        return new Test();
    }
    
    static void Main()
    {
        int a = 10;
        Test normalConversion = a;
        
        int? b = 20;
        Test unexpectedConversion = b;
        
        int? c = null;
        Test evenOdder = c;
    }
}

The first conversion (normalConversion = a) is entirely normal - int to Test, using the implicit conversion. This prints 10.

The second conversion (unexpectedConversion = b) is one which I didn't expect to be legal - after all, we have an int? rather than an int, and there's no implicit conversion from int? to int. However, it compiles and runs, and prints 20.

What would it print if we were to convert from a null value? Well, that's what the third conversion (evenOdder = c) checks. Again, it compiles and executes without an exception - but nothing gets printed. The result is a null reference.

It turns out that the C# compiler is handling this as a lifted conversion - so it checks whether or not the source has a value or not, and returns a null value if not. If there is a value, it performs the appropriate conversion.

This is a compiler bug (confirmed by Eric). It's not behaving as per the spec (which disallows it) but the behaviour is unlikely to change now as it would break existing code.