Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats the use of Nullable.GetUnderlyingType, if typeof(int?) is an Int32?

Tags:

c#

nullable

why is typeof int? an Int32

int? x = 1;
Console.WriteLine(x.GetType().Name);

If it is okay then what's the use of Nullable.GetUnderlyingType?

like image 980
Mubashir Khan Avatar asked Dec 23 '10 10:12

Mubashir Khan


People also ask

What is the purpose of a nullable type?

You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool , variable can only be either true or false .

What is the use of nullable types in C#?

The Nullable type allows you to assign a null value to a variable. Nullable types introduced in C#2.0 can only work with Value Type, not with Reference Type. The nullable types for Reference Type is introduced later in C# 8.0 in 2019 so that we can explicitly define if a reference type can or can not hold a null value.

Can Int32 be null?

Here, T represents the data type of the variable. The following statement would not compile as you cannot assign a null value to a value type. Int32 i = null; To assign a null value to a value type, you need to take advantage of a nullable type as shown in the code snippet below.

What is the difference between nullable int and int?

No difference. int? is just shorthand for Nullable<int> , which itself is shorthand for Nullable<Int32> . Compiled code will be exactly the same whichever one you choose to use.


3 Answers

Calling GetType() boxes your variable. The CLR has a special rule that Nullable<T> gets boxed to T. So x.GetType will return Int32 instead of Nullable<Int32>.

int? x = 1;
x.GetType() //Int32
typeof(int?) //Nullable<Int32>

Since a Nullable containing null will be boxed to null the following will throw an exception:

int? x = null;
x.GetType() //throws NullReferenceException

To quote MSDN on Boxing Nullable Types:

Objects based on nullable types are only boxed if the object is non-null. If HasValue is false, the object reference is assigned to null instead of boxing

If the object is non-null -- if HasValue is true -- then boxing occurs, but only the underlying type that the nullable object is based on is boxed. Boxing a non-null nullable value type boxes the value type itself, not the System.Nullable<T> that wraps the value type.

like image 131
CodesInChaos Avatar answered Sep 30 '22 14:09

CodesInChaos


This example is a bit confused, because:

int? x = 1;

creates a Nullable<int> like you expect; however:

Type type = x.GetType();

is a call to a non-virtual method on object, which isn't (and can't be) overridden - therefore this is a boxing operation; and Nullable<T> has special boxing rules:

  • if it is empty, it boxes to null
  • if it has a value, the value is boxed and returned

i.e.

int? x = 1;
int y = 1;

box to exactly the same thing.

Therefore, you are passing typeof(int) to GetUnderlyingType.

A more illustrative example of when this helps is when using reflection:

class Foo {
    public int? Bar {get;set;}
}
...
Type type = typeof(Foo); // usually indirectly
foreach(var prop in type.GetProperties()) {
     Type propType = prop.PropertyType,
          nullType = Nullable.GetUnderlyingType(propType);

     if(nullType != null) {
         // special code for handling Nullable<T> properties;
         // note nullType now holds the T
     } else {
         // code for handling other properties
     }
}
like image 31
Marc Gravell Avatar answered Sep 30 '22 15:09

Marc Gravell


Its for when you don't know its Int32.

Example:

    public Type GetNullableUnderlyingType<T>(Nullable<T> obj) 
        where T : struct
    {
        return Nullable.GetUnderlyingType(typeof(Nullable<T>));
    }

Here, you can pass any Nullable object and get it to return it's underlying type.

like image 4
decyclone Avatar answered Sep 30 '22 15:09

decyclone