This question already has answers here:
how are nullable types implemented under the hood in .net?
(2 answers)
Closed 6 years ago.
Generally when we access a property of a object which has a null value, we will face a null exception. But we when we access HasValue property of a Nullable object, it will gives a result. I would like to know what would be implementation behind the sceen.
If you didn't know already, nullable types, like int? are just Nullable<int>.
Nullable types in C# are just a "syntactic sugar". At compile time, the compiler replaces all the int? and double? and bool? with Nullable<int>, Nullable<double> and Nullable<bool>.
Note that Nullable<T> is actually a struct! So technically it can never be null! The reason why you can assign null to a nullable type is yet another syntactic sugar. When you assign null to a nullable type, it sets its HasValue property to false. When you assign a non-null value to it, it sets HasValue to true again and sets the underlying value to the value that you're setting.
That's a brief description of how nullable types works. Now back to your question:
But we when we access HasValue property of a Nullable object, it will gives a result
I guess you mean
But when we access HashValue property of a, say int?, it will never throw an exception, even if the variable is null! Why?
As I said before, Nullable<T> is a struct, so it can never be null. That's why you can access the HasValue property and never throw an exception.
"But why accessing the Value property of a nullable object sometimes throws an exception?" you might ask.
That's because of the implementation of the Nullable<T> struct. As you can see here:
public T Value {
get {
if (!hasValue) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
}
return value;
}
}
It checks that if hasValue is true. If it is false, throw an exception.
So that's why.
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
This question already has answers here:
How does the assignment of the null literal to a System.Nullable<T> type get handled by .Net (C#)?
(5 answers)
Closed 8 years ago.
Recently while revising one of the concept I came across a situation which is interesting and I want to know why this happens.
We know one concept that we can't assign null values to Value types i.e. Struct, int, DateTime, etc.
In order to assign null we need nullable type i.e.
int i should be replaced with Nullable<int> i = null
But if we see Nullable<T> it is also of type struct then how come null can be assigned without stating any error? Why Microsoft contradicted it's own statement of "Null can't be assigned to value type"
If someone knows the reason behind this?
Because Nullable<T> has compiler-level support; null, in the context of Nullable<T>, is essentially a value with a HasValue flag of false, where-as a non-null value has a HasValue flag of true. And similarly, "lifted" operators are derived from the defined operators. Likewise, Nullable<T> has CLI support, in terms of boxing: a boxed Nullable<T> with HasValue of false becomes null, not a new box instance.
Basically: it all just comes down to because that is how they defined it should work.
People wanted nullable value types: Microsoft figured out a way for that to happen.
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.
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
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