13

I have read on MSDN that:

The null keyword is a literal that represents a null reference, one that does not refer to any object.

But I've seen the following code running without throwing any exception:

int? i = null;
var s = i.ToString();

So if the variable i is null, why can I execute it's method?

Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53
Buda Gavril
  • 21,409
  • 40
  • 127
  • 196
  • https://msdn.microsoft.com/en-us/library/2cf62fcy.aspx – Pat Jan 24 '17 at 19:50
  • 2
    Think about it, you have to be able to call `i.HasValue` to determine if it's null or not....how would you be able to do that if there weren't always an instance present. – rory.ap Jan 24 '17 at 19:51
  • In that particular case you can always check the .net source code: https://referencesource.microsoft.com/mscorlib/system/nullable.cs.html#d83d2db767b43db7 `public override string ToString() { return hasValue ? value.ToString() : ""; }` – Gonan Jun 12 '19 at 10:55

2 Answers2

21

Because int? is actually a Nullable<Int32> and Nullable<T> is a struct, and a structure cannot be null.

It is just how Nullable types work. They are not reference values, so they can't be null, but they can have a state when they are considered equivalent to null.

You can get more details about Nullable<T> implementation in how are nullable types implemented under the hood in .net? and Nullable<T> implementation


Though as pointed by @JeppeStigNielsen there is one case when you can get a NRE:

However: When boxed to a reference type, special treatment of Nullable<> ensures we do get a true null reference. So for example i.GetType() with i as in the question will blow up with the NullReferenceException. That is because this method is defined on object and not overridable

Community
  • 1
  • 1
Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53
  • And if you look at the [Nullable(T).ToString](https://msdn.microsoft.com/en-us/library/9hd15ket(v=vs.110).aspx) docs it mentions that you get an empty string when `HasValue` is false. – pstrjds Jan 24 '17 at 19:54
  • but then why in the debugger variable i shows as null? – Buda Gavril Jan 24 '17 at 20:01
  • @BudaGavril Because debugger knows about `Nullable` type and slightly cheats to make it look null when it has no value. – Eugene Podskal Jan 24 '17 at 20:02
  • I see, so the debugger misleads here... I wonder if this is indeed a cheat or a bug... – Buda Gavril Jan 24 '17 at 20:05
  • 1
    @BudaGavril It is not a bug, because that's what one usually expects to see after setting variable to null. Though, perhaps, it would have been less misleading to somehow indicate that such `null` is not a `null` in the true sense of that word. – Eugene Podskal Jan 24 '17 at 20:09
  • 3
    However: When boxed to a reference type, special treatment of `Nullable<>` ensures we do get a true null reference. So for example `i.GetType()` with `i` as in the question ___will___ blow up with the `NullReferenceException`. That is because this method is defined on `object` and not overridable. – Jeppe Stig Nielsen Jan 24 '17 at 20:20
  • @JeppeStigNielsen Thanks, didn't think about that case - added to the answer with attribution. – Eugene Podskal Jan 24 '17 at 20:26
7

The code you pasted

int? i = null;

is actually just a shorthand for

int? i = new int?();

Which is a shorthand for

Nullable<int> i = new Nullable<int>();

Assigning null is using the implicit operator which you can read more from here MSDN.

Janne Matikainen
  • 5,061
  • 15
  • 21
  • where did you found this? can you give me a link? – Buda Gavril Jan 24 '17 at 20:00
  • https://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx "The syntax T? is shorthand for Nullable, where T is a value type. The two forms are interchangeable." – Janne Matikainen Jan 24 '17 at 20:01
  • Assigning null is not using that implicit operator. Assigning like `int? i = 42;` can be thought of as using that implicit operator. However, C# will have its own built-in implicit conversion from `int` to `int?` so I do not think the C# compiler will actually "issue" a call to the IL method you link. And in case of assigning null, it is sure that the C# built-in implicit conversion from the literal `null` to the type `int?` must be considered to understand why it works. – Jeppe Stig Nielsen Jan 24 '17 at 20:35