The '.' operator on null nullable - c#

How is it that you can access null nullable's propery HasValue?
I looked to the compiled code, and it's not a syntactic sugar.
Why this doesn't throw NullReferenceException:
int? x = null;
if (x.HasValue)
{...}

That's because int? is short for Nullable<int> which is a value type, not a reference type - so you will never get a NullReferenceException.
The Nullable<T> struct looks something like this:
public struct Nullable<T> where T : struct
{
private readonly T value;
private readonly bool hasValue;
//..
}
When you assign null there is some magic happening with support by the compiler (which knows about Nullable<T> and treats them special in this way) which just sets the hasValue field to false for this instance - which is then returned by the HasValue property.

Like BrokenGlass said, an int? is actually a Nullable<T>.
Structures always contain a value. Usually you cannot set a structure variable to null, but in this special case you can, essentially setting it to default(Nullable<T>). This sets its contents to null rather than the variable itself.
When you set a Nullable<T> to a value, it uses an implicit operator to set Value = value to the new value and HasValue = true.
When you set Nullable<T> to null, it nulls all of the structure's fields. For a bool field such as HasValue, null == false.
Since a Nullable<T> variable is a structure, the variable can always be referenced because its contents is null rather than the variable itself.
There's more information on structures in the Remarks section of the MSDN page struct.

Related

How is it possible for me to call HasValue on a null object? [duplicate]

This question already has answers here:
Why does Nullable<T> HasValue property not throw NullReferenceException on Nulls?
(5 answers)
Closed 6 years ago.
Consider the following code:
int? myInt = null;
var hasValue = myInt.HasValue;
This is perfectly acceptable, and HasValue will return false. But how have I managed to reference a property on an object that is null? The following wouldn't work:
public class MyClass
{
public bool MyBool { get { return true; } };
}
// Elsewhere in code...
MyClass myObject = null;
myObject.MyBool;
This would raise a null reference exception. The fact I'm comparing the two code snippets above as though they are equal tells me that I'm misunderstanding a structure or some syntax somewhere.
Can somebody please tell me why code snippet 1 does not raise an exception, but why my code snippet 2 would?
In the first case, you have a value of type Nullable<int>, which is "the null value for the type". The Nullable<T> type is a value type with two fields, like this:
public struct Nullable<T> where T : struct
{
private T value;
private bool hasValue;
}
When you use the null literal with a Nullable<T>, you're really just creating a value where the value field has the default value of T, and hasValue is false. Using the HasValue property isn't following a reference - it's just getting a field out of the struct.
In the second case, the value of myObject is a null reference... so if you try to use the MyBool property, that fails because it's trying to find an object when there isn't one.
So the key points are:
Nullable<T> is a struct, not a class
The value of a variable of type Nullable<T> is just a value with two fields, not a reference
The null literal just means "the null value of the relevant type", it does not always mean a null reference.

? (nullable) operator in C# [duplicate]

This question already has answers here:
What is the purpose of a question mark after a value type (for example: int? myVariable)?
(9 answers)
Closed 5 years ago.
What is changed by applying nullable Operator on value type datatype that now it can store null.
As others have said, "?" is just shorthand for changing it to Nullable<T>. This is just another value type with a Boolean flag to say whether or not there's really a useful value, or whether it's the null value for the type. In other words, Nullable<T> looks a bit like this:
public struct Nullable<T>
{
private readonly bool hasValue;
public bool HasValue { get { return hasValue; } }
private readonly T value;
public T value
{
get
{
if (!hasValue)
{
throw new InvalidOperationException();
}
return value;
}
}
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
// Calling new Nullable<int>() or whatever will use the
// implicit initialization which leaves value as default(T)
// and hasValue as false.
}
Obviously in the real code there are more methods (like GetValueOrDefault()) and conversion operators etc. The C# compiler adds lifted operators which effectively proxy to the original operators for T.
At the risk of sounding like a broken record, this is still a value type. It doesn't involve boxing... and when you write:
int? x = null;
that's not a null reference - it's the null value of Nullable<int>, i.e. the one where hasValue is false.
When a nullable type is boxed, the CLR has a feature whereby the value either gets boxed to a null reference, or a plain boxed T. So if you have code like this:
int? x = 5;
int y = 5;
object o1 = x;
object o2 = y;
The boxed values referred to by o1 and o2 are indistinguishable. You can't tell that one is the result of boxing a nullable type.
The ? syntax is syntactic sugar to the Nullable<T> struct.
In essence, when you write int? myNullableInt, the compiler changes it to Nullable<int> myNullableInt.
From MSDN (scroll down to "Nullable Types Overview"):
The syntax T? is shorthand for Nullable, where T is a value type. The two forms are interchangeable.
Nothing is changed on the value type itself, it's simply wrapped in a System.Nullable<T> struct.
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
The type changes from what it used to be to a Nullable type.
If you had an int, and decided to make it an int?:
int myInt;
And you make it:
int? myInt;
it is now:
Nullable<int> myInt;
In reality.
In basic terms, a nullable type is a boxed version of the normal type that has an extra boolean field called hasValue on it.
When this field is set to false, then the instance is null.
Check out this answer for a bit more detail on the CLR implementation, and why they might have chosen it: Boxing / Unboxing Nullable Types - Why this implementation?

Reflection - check all nullable properties have values

I have to loop through all the properties in a few classes and check any nullable properties to see if they have a value. How do I cast the value returned from propertyInfo.GetValue() to a generic nullable type so that I can check the HasValue property?
Code snipped for brevity:
foreach (PropertyInfo propInfo in this.GetType().GetProperties())
{
if (<Snip: Check to see that this is a nullable type>)
{
//How do i cast this properly in here to allow me to do:
if(!((Nullable)propInfo.GetValue(this, null)).HasValue)
//More code here
}
}
note I'm assuming you mean Nullable<T>; if you mean Nullable<T> or a reference, then you already have it: object (from GetValue) - just check for null.
In the case of Nullable<T>; you can't cast to a single non-generic type (other than object) - but you don't need to; just check that it isn't null, since empty Nullable<T> is boxed to null, and GetValue returns object (hence it boxes the value).
if(Nullable.GetUnderlyingType(propInfo.PropertyType) != null) {
// it is a Nullable<T> for some T
if(propInfo.GetValue(this, null) != null) {
// it has a value (it isn't an empty Nullable<T>)
}
}
To clarify, Nullable is a static utility class that is completely separate to the Nullable<T> struct; so you don't cast to Nullable at all. As it happens, Nullable exists to provide things like the GetUnderlyingType that helps you work with Nullable<T>.
Since you've established that the property is of type Nullable<something>, you know its value has a HasValue property - so find that property by reflection and get its value.

Is Nullable<T>.Equals Method Implementation Wrong?

I am talking about C# language here.
Definition of Object.Equals(Object) method in msdn is:
Determines whether the specified
Object is equal to the current Object.
If two objects are equal it returns true, however if they are null it returns false:
x.Equals(a null reference (Nothing in
Visual Basic)) returns false.
Why? Because null is not an object.
A NullReferenceException is thrown if the object paremeter is null.
and also we have this:
x.Equals(y) returns the same value as
y.Equals(x).
No problem at all till here. It is very similar to Java. But C# also provides a System.Nullable struct for non-nullable types. As far as I know, a struct is an object. It inherits Object.Equals method.
If I have a struct like this:
struct Car
{
public string Make;
public string Model;
public uint Year;
public Car(string make, string model, uint year)
{
Make = make;
Model = model;
Year = year;
}
}
And create four instances:
Car car1 = new Car("make", "model", 2009);
Car car2 = new Car("make", "model", 2009);
Car car3 = new Car("make", "model", 2008);
car1.Equals(car2); // will return true
car1.Equals(car3); // will return false;
And as far as I know we can't set a struct to a null value. But System.Nullable is a struct and we can do compile this without any errors:
int? i = null;
(I hope that someone can explain this also. Is it a struct or something else?)
My real question is:
i.Equals(null); // returns true!
(Normally x.Equals(y) = y.Equals(x) Of course null.Equals(i) is not valid here... )
Obviously Object.Equals method is overridden here. Maybe it is documented and this is specified. But is this approach correct/nice ? If so what is the difference between == and Equals method for Nullable values?
I think your confusion is rooted in the following line
i? = null;
This does not actually create a null value variable. It's essentially syntatic sugar for the following
Nullable<int> i = new Nullable<int>();
The resulting property HasValue on i will have the value false. It is not null but instead a value type with empty values. Or just an empty nullable. IMHO, the best way to think of this is that null is convertible to an empty Nullable<T> for any given T.
Knowing that it makes the line i.Equals(null) a bit easier to understand. It's syntatic sugar for the following
Nullable<int> i = new Nullable<int>();
i.Equals(null);
The type Nullable<T> only overrides Equals(object). The implementation of this method though considers a null value to be Equal to an empty nullable value. So it's behaving correctly.
To answer your side question, Nullable is a struct with a T: Struct constraint. So, even though int? i = null; is null, i is an instance of the Nullable struct.

Why does nullable KeyValuePair<,> have no key property?

I have the following:
KeyValuePair<string, string>? myKVP;
// code that may conditionally do something with it
string keyString = myKVP.Key;
// throws 'System.Nullable<System.Collections.Generic.KeyValuePair<string,string>>'
// does not contain a definition for 'Key'
I'm sure there is some reason for this as I can see that the type is nullable. Is it because I am trying to access the key when null could cause bad things to happen?
Try this instead:
myKVP.Value.Key;
Here is a stripped down version of System.Nullable<T>:
public struct Nullable<T> where T: struct
{
public T Value { get; }
}
Since the Value property is of type T you must use the Value property to get at the wrapped type instance that you are working with.
Edit: I would suggest that you check the HasValue property of your nullable type prior to using the Value.
if (myKVP.HasValue)
{
// use myKVP.Value in here safely
}
This is because nullable types can be assigned null value or the actual value, hence you have to call ".value" on all nullable types. ".value" will return the underlying value or throw a System::InvalidOperationException.
You can also call ".HasValue" on nullable type to make sure that there is value assigned to the actual type.

Categories

Resources