Is the Nullable Type Not a Null Type?

I tested several types with a null value, and it did not work as I expected:

int? testInt = 0; Type nullableType = typeof(int?); Assert.AreEqual(nullableType, testInt.GetType()); // not the same type 

This also does not work:

 DateTime? test = new DateTime(434523452345); Assert.IsTrue(test.GetType() == typeof(Nullable)); //FAIL DateTime? test = new DateTime(434523452345); Assert.IsTrue(test.GetType() == typeof(Nullable<>)); //STILL FAIL 

My question is why testInt.GetType () returns int, and typeof (int?) Returns true type NULL?

+41
c # nullable gettype
Apr 24 '09 at 10:44
source share
4 answers

According to MSDN :

Calling GetType of type Nullable causes a boxing operation to be performed when the type is implicitly converted to an object. Therefore, GetType always returns a Type object, which is a base type, not a Nullable type.

When you place an object with a null value, only the base type is inserted.

Again, from MSDN :

Boxing a non-empty value type NULL inserts the value type, not System.Nullable, which wraps the value type.

+53
Apr 24 '09 at 10:46
source share
β€” -

In addition to Romain's correct answer, if you want to compare β€œreal” types (that is, without implicitly converting any type with a null type to its base type), you can create an extension method as follows:

 public static class MyExtensionMethods { public static Type GetRealType<T>(this T source) { return typeof(T); } } 

And then try the following tests:

 int? a = 0; Console.WriteLine(a.GetRealType() == typeof(int?)); // True Console.WriteLine(a.GetRealType() == typeof(int)); // False int b = 0; Console.WriteLine(b.GetRealType() == typeof(int)); // True Console.WriteLine(b.GetRealType() == typeof(int?)); // False DateTime? c = DateTime.Now; Console.WriteLine(c.GetRealType() == typeof(DateTime?)); // True Console.WriteLine(c.GetRealType() == typeof(DateTime)); // False DateTime d = DateTime.Now; Console.WriteLine(d.GetRealType() == typeof(DateTime)); // True Console.WriteLine(d.GetRealType() == typeof(DateTime?)); // False 

EDIT ...

For completeness - and suggested by SLaks comments below - here is an alternative version that uses only the compile time type when source is either null or Nullable<> ; otherwise, it uses GetType and returns the type of runtime:

 public static class MyExtensionMethods { public static Type GetRealType<T>(this T source) { Type t = typeof(T); if ((source == null) || (Nullable.GetUnderlyingType(t) != null)) return t; return source.GetType(); } } 
+22
Apr 24 '09 at 12:14
source share

Despite the fact that C # pretends that value type storages store instances of types obtained from System.ValueType , which, in turn, come from System.Object , this is not so. Each type derived from System.ValueType actually represents two very different types of things:

  • A set of bytes that (for primitive types) represents data directly, or (for non-primitive structure types) contains the contents of all fields, public and private, but does not contain information about the type.
  • A separate heap object that contains the object header in addition to the above, whose type is derived from `System.ValueType`.

A value type storage location holds the first; heaps of objects of type value hold the second.

For various reasons, Microsoft decided that Nullable<T> should only support first use. If you try to pass a storage location of type Nullable<T> to code that expects a reference to the heap object, the system converts the element to T if HasValue is true, or just pass a null reference if HasValue is false. Although there are ways to create a heap object of type Nullable<T> , the usual methods of converting a store of values ​​of a type to a heap object will never generate one.

Please also note that calling GetType() in the storage location of the value will not actually determine the type of storage location, but instead converts the contents of this storage location to a heap object and then returns the type of the resulting object, since storage locations of type Nullable<T> converted either to instances of the object T , or to zero, nothing in the instance of the object will tell if the storage location from which it was was Nullable<T> .

+3
Apr 2 2018-12-12T00:
source share

A simple way to check if the "is" operator is using:

 (i is Nullable<int>) || (i is Nullable<long>) || (i is Nullable<float>) || (i is Nullable<short>) 

I realized that I was reading these two MSDN pages:

http://msdn.microsoft.com/en-us/library/ms366789(v=vs.90).aspx

http://msdn.microsoft.com/en-us/library/ms228597%28v=VS.90%29.aspx

Hurrah!

+1
Nov 12 '13 at
source share



All Articles