7

In C# 3.0 you can assign null to int? type (in CLR int? is a struct):

int? a = null;

but when you define a custom struct:

struct MyStruct
{

}

there's an error during the compilation of this code:

MyStruct a = null;

The error is as follows:

Cannot convert null to 'Example.MyStruct' because it is a non-nullable value type

While int? is a struct in CLR it is somehow counterintuitive that we can assign null to it. I suppose that null is implicitly casted or boxed to a certian int? value that represents the null value. How is it done precisely? How can I extend MyStruct in such a way that it would be possible to execute the line:

MyStruct a = null;
mgamer
  • 13,580
  • 25
  • 87
  • 145

3 Answers3

20

It's because int? is actually shorthand Nullable<int>. You can do the same thing for your type too:

MyStruct? a = null;

null can only be implicitly converted to a nullable type, which means any reference type or any nullable value type - where the latter means Nullable<T> for some T.

Note that this ability to conver from null is really a language feature - the compiler is converting this:

int? a = null;

into

int? a = new int?();

They mean the same thing - basically a "null" value for a nullable value type is a value where HasValue is false, which it will be by default. It's not the same as a null reference - although boxing a null value like that will result in a null reference.

(This is one example of a feature which crosses language, library and CLR boundaries. The library part is quite simple, the CLR part is only to do with boxing and unboxing - but there's quite a lot in terms of lifted operators etc in the language.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Interesting timing of this question. I just got done reading the chapter about nullable types in Jon's book (C# in Depth) . Every C# developer should read it!! Thanks Jon. – Bryan Nov 24 '10 at 18:17
  • I'd just like to point out that I didn't pay for that comment :) – Jon Skeet Nov 24 '10 at 18:21
  • Your statement "Note that this is really a language feature" is somewhat confusing since the CLR *does* (as you mention later on) handle `Nullable<>` structs specially in boxing and unboxing operations, which IMHO makes this a runtime feature (with some `?` syntactic sugar to top it off). – Lucero Nov 24 '10 at 18:22
  • @Lucero: The conversion from the null literal is a language feature. I'll edit to make that clearer. – Jon Skeet Nov 24 '10 at 18:26
  • @Jon Skeet: So my problem lies with the language feature that you've mentioned. Is it possible to somehow utilize that language feature to automatically convert MyStruct a = null to MyStruct a = new MyStruct() ? – mgamer Nov 24 '10 at 18:26
  • @mgamer: No; it's only applicable to `Nullable`. – Jon Skeet Nov 24 '10 at 18:28
  • @Jon, I see what you mean. One more comment-question though: Why did you chose to write `new int?()` instead of `default(int?)` (which is true for all nullable types, be it reference or `Nullable<>`)? (Edit: this would address mgamer's comment as well.) – Lucero Nov 24 '10 at 18:33
2

Structs are value types in C#, not reference types, so they can't be null.

MyStruct? = null;

will work, but remember that structs are immutable, as a example:

public struct Point 
{
   public int x, y;

   public Point(int p1, int p2) 
   {
       x = p1;
       y = p2;    
   }
}

void Main()
{

    //create a point
    var point1 = new Point(10, 10); 

    //assign point2 to point, point2
    var point2 = point1; 

    //change the value of point2.x
    point2.x = 20; 

    //you will notice that point1.x does not change
    //this is because point2 is set by value, not reference.
    Console.WriteLine(point1.x);
    Console.WriteLine(point2.x);

}
Master Morality
  • 5,837
  • 6
  • 31
  • 43
1

just adding, a nullable type can represent the normal range of values for its underlying value type, plus an additional null value.

In notation, just as int is actually Int32, not any int, the ? sign means a nullable. Nullable, in this case.

http://msdn.microsoft.com/en-us/library/1t3y8s4s%28VS.80%29.aspx

marcelo-ferraz
  • 3,147
  • 4
  • 38
  • 55