Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can an int? set to null have instance properties?

Tags:

c#

.net

nullable

I'm curious as to why the following code works (run under the VS debugger):

int? x = null;
null
x.HasValue
false

If x is indeed null, what instance does HasValue refer to? Is HasValue implemented as an extension method, or does the compiler special case this to make it magically work?

like image 458
Mike Christensen Avatar asked Dec 20 '11 20:12

Mike Christensen


People also ask

Can an int be Nullable?

Java primitive types (such as int , double , or float ) cannot have null values, which you must consider in choosing your result expression and host expression types.

Can a int be null in C#?

As you know, a value type cannot be assigned a null value. For example, int i = null will give you a compile time error. C# 2.0 introduced nullable types that allow you to assign null to value type variables.

Is Nullable int a value type?

Nullable types are neither value types nor reference types.


4 Answers

Because x isn't a reference type. The ? is just syntactic sugar for Nullable<T>, which is a struct (value type).

like image 70
Cameron Avatar answered Sep 20 '22 15:09

Cameron


int? is actually a structure Nullable<int>. Hence this, your x cannot be null, because it is always instance of a structure.

like image 27
Sergei B. Avatar answered Sep 18 '22 15:09

Sergei B.


Hand-waving answer: Nullable structs are magic.

Longer answer: Null is not actually what is represented by the value. When you assign null to a nullable struct, what you will see happen behind the scenes is different.

int? val = null; // what you wrote 
Nullable<Int32> val = new Nullable<Int32>(); // what is actually there

In this case, an instance of the struct is created that has the T Value set to a default value and the bool HasValue property set to false.

The only time you will actually obtain a null reference from a Nullable<T> is when it is boxed, as a Nullable<T> boxes directly to T or null, depending upon if the value is set.

like image 24
Anthony Pegram Avatar answered Sep 19 '22 15:09

Anthony Pegram


There are several meanings to null.

One in programming languages which present variables and memory in a pointer-based manner (which includes C#'s references though it hides some of the details) is "this doesn't point to anything".

Another is "this has no meaningful value".

With reference types, we often use the former to represent the latter. We might use string label = null to mean "no meaningful label. It remains though that it's still also a matter of what's going on in terms of what's where in memory and what's pointing to it. Still, it's pretty darn useful, what a shame we couldn't do so with int and DateTime in C#1.1

That's what Nullable<T> provides, a means to say "no meaningful value", but at the level below it's not null in the same way a null string is (unless boxed). It's been assigned null and is equal to null so it's logically null and null according to some other semantics, but it's not null in the "doesn't point to anything" implementation difference between reference and value types.

It's only the "doesn't point to anything" aspect of reference-type null that stops you from calling instance methods on it.

And actually, even that isn't strictly true. IL let's you call instance methods on a null reference and as long as it doesn't interact with any fields, it will work. It can't work if it needs (directly or indirectly) those fields since they don't exist on a null refernce, but it could call null.FineWithNull() if that method was defined as:

int FineWithNull()
{
  //note that we don't actually do anything relating to the state of this object.
  return 43;
}

With C# it was decided to disallow this, but it's not a rule for all .NET (I think F# allows it, but I'm not sure, I know unmanaged C++ allowed it and it was useful in some very rare cases).

like image 20
Jon Hanna Avatar answered Sep 20 '22 15:09

Jon Hanna