The Nullable<T> type is defined as a struct. In .Net, you can't assign null to a struct because structs are value types that cannot be represented with null (with the exception of Nullable<T>).
int i = null; // won't compile - we all know this
int? i = null; // will compile, and I'm glad it does, and it should compile, but why?
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?" The decompiled code for Nullable<T> offers no insights as of to how this happens.
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?"
By changing the language, basically. The null literal went from being "a null reference" to "the null value of the relevant type".
At execution time, "the null value" for a nullable value type is a value where the HasValue property returns false. So this:
int? x = null;
is equivalent to:
int? x = new int?();
It's worth separating the framework parts of Nullable<T> from the language and CLR aspects. In fact, the CLR itself doesn't need to know much about nullable value types - as far as I'm aware, the only important aspect is that the null value of a nullable value type is boxed to a null reference, and you can unbox a null reference to the null value of any nullable value type. Even that was only introduced just before .NET 2.0's final release.
The language support mostly consists of:
Syntactic sugar in the form of ? so int? is equivalent to Nullable<int>
Lifted operators
The changed meaning of null
The null-coalescing operator (??) - which isn't restricted to nullable value types
Related
The Nullable<T> type is defined as a struct. In .Net, you can't assign null to a struct because structs are value types that cannot be represented with null (with the exception of Nullable<T>).
int i = null; // won't compile - we all know this
int? i = null; // will compile, and I'm glad it does, and it should compile, but why?
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?" The decompiled code for Nullable<T> offers no insights as of to how this happens.
How did Nullable<T> become an exception to the rule "You can't assign null to a value type?"
By changing the language, basically. The null literal went from being "a null reference" to "the null value of the relevant type".
At execution time, "the null value" for a nullable value type is a value where the HasValue property returns false. So this:
int? x = null;
is equivalent to:
int? x = new int?();
It's worth separating the framework parts of Nullable<T> from the language and CLR aspects. In fact, the CLR itself doesn't need to know much about nullable value types - as far as I'm aware, the only important aspect is that the null value of a nullable value type is boxed to a null reference, and you can unbox a null reference to the null value of any nullable value type. Even that was only introduced just before .NET 2.0's final release.
The language support mostly consists of:
Syntactic sugar in the form of ? so int? is equivalent to Nullable<int>
Lifted operators
The changed meaning of null
The null-coalescing operator (??) - which isn't restricted to nullable value types
The MSDN mentions that overloading the = operator is not possible.
How is it possible then for Nullable types to be assigned to null?
int? i = null;
Besides can I do it with my own generic types and how?
It's the implicit-conversion not the assignment-operator that allows to assign null: http://msdn.microsoft.com/en-us/library/ms131346(v=vs.110).aspx
If the value parameter is not null, the Value property of the new
Nullable<T> value is initialized to the value parameter and the
HasValue property is initialized to true. If the value parameter is
null, the Value property of the new Nullable<T> value is initialized
to the default value, which is the value that is all binary zeroes,
and the HasValue property is initialized to false.
Essentially what Tim's comment (Edit: And now answer =D) says - There's an implicit conversion from the null literal, rather than an overload of the assignment operator.
From the C# language spec (I was looking at Version 5.0) - Section "6.1.5 Null literal conversions":
An implicit conversion exists from the null literal to any nullable
type. This conversion produces the null value (ยง4.1.10) of the given
nullable type.
There is special compiler support for the Nullable type.
It is impossible to create a user-defined implicit conversion to/from null. They built it into the language (and the runtime) rather than creating Nullable on top of the language, as so many BCL classes are made.
Interestingly this is not the only special support created for Nullable. When you box a Nullable<T> it doesn't actually box a Nullable object, ever. If HasValue is false, null is boxed, and if it's true, the underlying value is unwrapped and boxed. It would be impossible to do this for your own type.
Nullable types are instances of the struct
System.Nullable<T>.
The type that can be specified or made nullable is specified as the generic type of nullable (T).
More info here...http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
In your example, you're not actually setting an int to null, rather setting the value on the struct which encapsulates it to null.
Originally I had this impression that NULL is reference type because it is assigned to references, then encountered this concept called nullable value types, this makes my theory in an awkward situation, so is NULL value type of reference type on earth ?
The C# specification is clear on this point: the null keyword represent an expression that has no type. It is neither reference type nor value type nor pointer type. However that expression is convertible to all of those types. There is no requirement that the compiler classify all expressions as having a type, and in fact it does not.
Now you might then ask at runtime what is the type of a null reference, what is the type of a null value of nullable value type, and what is the type of a null pointer. The answers are:
a null reference does not have a type. If you have a box that can hold chocolates it is pointless to ask "what brand of chocolates are in this empty box?" A missing chocolate does not have a brand; a null reference does not have a type.
similarly, the type of a null pointer is, again, not anything; null pointer values don't point to anything. If you have a piece of paper that has the address 1600 Pennsylvania Avenue on it, you can ask "what is the colour of the house at this address", and get the answer: white. If you have a blank piece of paper, asking what the colour of the house at that address is doesn't get you any useful answer.
a null value of a nullable value type is a value of the nullable value type.
null isn't a type.
From msdn:
The null keyword is a literal that represents a null reference, one that does not refer to any object.
Nullable types are instances of the Nullable<T> struct which "Represents a value type that can be assigned null."
Neither. null is the default value for reference types, but it does not have a type itself.
Nullable value types are actually implemented as value types themselves - there are just compiler and library tricks to make them behave as expected when compared to null.
null doesn't have a type by itself in C#, as it was already said here. I think some precise examples showing the implications of this definition are missing from the other answers.
var something = null;
is invalid
string a = null; // valid. Null is implicitely casted to string.
int? b = null; // valid. Null is implicitely casted to Nullable<int>.
var c = "hello" // valid, type of c is infered by the compiler by looking at the right side of the expression.
var d = null; // not valid, compiler can't infer any type from null !
The invalid line in the above example will cause the following compilation error :
Error - CS0815 - Cannot assign to an implicitly-typed variable
and also :
Passing null to overloaded methods might require an explicit cast
void myMethod(int? myParam) { }
void myMethod(string myParam) { }
void test
{
string a = null;
myMethod(a); // no problem here, a is of type string so 2nd overload will be used.
myMethod(null); // not valid ! Compiler can't guess which one you want.
myMethod((string) null); // valid, null is casted to string so 2nd overload is to be used.
}
The invalid line in the above example will cause the following compilation error :
Error - CS0121 - The call is ambiguous between the following methods
or properties: 'myMethod(string)' and 'myMethod(int?)'
null does not reference to anything. It is just a type points to nothing. You people usually use it to de-reference an object.
The null keyword in C# does represent a null reference, so you can consider it a reference type (although technically it indicates not type).
The C# compiler and extra handling of null for use with nullable types. Nullable value types and value types and can never actually be null. When you assign or compare a Nullable value type to null the compiler will replace the code.
For example:
int? i;
if (i == null)
i = 1;
Is replaced by the compiler with:
int? i;
if (!i.HasVaue)
i = 1;
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the difference between 'int?' and 'int' in C#?
I've come across some code in C# that declares a variable as: int? number
What does the ? mean and how does this differ from just: int
int cannot be null.
int? is an alias for the Nullable<int> struct, which you can set to null.
int? is a shorthand for creating an instance of the generic System.Nullable<T> structure type. It allows you to make your variable nullable. Remember, given that the <ValueType>? syntax is a shorthand, you could declare your variables thus:
Nullable<int> i = 10;
int? is shorthand for Nullable<int> which allows you to pretend that an integer can handle nulls.
int? foo = null;
It is useful for indicating a lack of value where you would previously have used a magic value (-1) in the past, and also useful when dealing with database columns that allow null entries.
For a quasi-in-depth look, a Nullable<T> (introduced in .NET 2.0) is simply a wrapper over a value type T that exposes two properties, HasValue and Value, where HasValue is a boolean that indicates if the value has been set and Value (obviously enough) returns the value. It is an error to access Value if HasValue is false. Therefore, to access Value, it is good form to check HasValue first. Additionally, if you simply want to normalize any non-values to default values (0 for numeric types), you can use the method GetValueOrDefault() without needing to check HasValue.
Note that although you appear to set foo to null, it's not actually null under normal usage scenarios. null is simply additional syntactic sugar for this type. The above line of code translates to
Nullable<int> foo = new Nullable<int>();
Initializing the variable in this fashion simply sets the HasValue property to false.
However, in situations involving boxing, the value will actually box to null if HasValue is false (it will otherwise box to T). Be aware of the consequences! For example, in:
int? foo = null;
string bar = foo.ToString(); // this is fine, returns string.Empty
Type type = foo.GetType(); // blows up! GetType causes the value to box
// resulting in a NullReferenceException
That's a quick crash course. For more, visit the documentation.
It's syntactic compiler sugar for Nullable<int>
Basically your number (or any other value type) can be null as well as it's value. You check for a value using the HasValue property. They can be cast into their value types (although this will fail if they're null) or you can use the Value property (again it will throw an exception if it is null)
One thing which usually appears to be overlooked when using nullable types is the GetValueOrDefault() method which returns default(T) if the object is null.
As #Kyle Trauberman points out in the comment you can indeed compare it to null instead of checking HasValue. The type itself is a value type with overriden equality methods so that much as it will never be null itself it will return true when compared to null if it doesn't have a value.
A questionmark behind the declaration means that the variable is nullable.
int? can be null where as int can not.
Reference Nullable Types:
http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=VS.100).aspx
Basically, Nullable<T> is a structure, which explains things like calling .HasValue will never throw a NullReferenceException. I was wondering why - given a nullable which does not have a value - comparisons to null are always true, even when using Object.ReferenceEquals, which I thought would return false because it is a structure.
Is there special behaviour built into the CLR to make this possible? It would probably also explain why the generic struct constraint does not allow nullables.
Best Regards,
Oliver Hanappi
If you do:
int? x = null;
if (x == null)
that will use HasValue.
Using Object.ReferenceEquals will box the value first - and that will convert the null value into a null reference (which is indeed special CLR behaviour). When a nullable value type is boxed, the result is either a null reference or a box of the underlying value type. In other words, there's no such thing as a boxed value of a nullable value type.
Nullable comparisons do not always return true. Take this example, for instance:
int? n = null;
int? m = 5;
Console.WriteLine(n == null); // prints True
Console.WriteLine(m == null); // prints False
The CLR has special boxing behavior for Nullables, such that reference comparison works as you might expect. Essentially, the Value property of the struct is boxed into an object.
Yes, Nullable<T> is a special struct that enjoys compiler support. I have blogged about what happens when it gets compiled into IL here.