0

How does the Nullable class do it?

public class Foo<T>
{
    public T Bar { get; set; }
}

var n1 = new Nullable<int>(123).GetType().Name; // "Int32"
var n2 = new Foo<int>().GetType().Name; // "Foo`1"

Is it possible to make Foo have the same type name, i.e. "Int32"?

l33t
  • 18,692
  • 16
  • 103
  • 180
  • 5
    Note that `Nullable` gets some very special treatment by the runtime. In particular, if a `Nullable` without a value is boxed, the boxed object is `null` -- in contrast to every other value type. My suspicion is that this is similar special treatment. – cdhowie Sep 08 '17 at 13:34
  • See also [How is ValueType.GetType() able to determine the type of the struct?](https://stackoverflow.com/q/926352/1207195). Because `Nullable` is a `ValueType` and value types are boxed then it's what you get (see also [Nullable.cs](https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/nullable.cs) source code) – Adriano Repetti Sep 08 '17 at 13:46
  • The answer is a combination of my comment and @AdrianoRepetti's. I will draft an answer. – cdhowie Sep 08 '17 at 14:11

1 Answers1

2

tl;dr: No, you can't change the name of Foo. What you're seeing with Nullable is a side-effect of how nullable values are boxed.


There are a few things at play causing the behavior you see regarding the Nullable type:

  • Invoking .GetType() on a value type causes the value to be boxed.
  • Nullable gets special treatment by the runtime regarding boxing. A Nullable itself is never boxed, instead:
    • If the Nullable contains a value, that value is boxed (the int value 123 in this case).
    • If the Nullable does not contain a value, the boxing operation evaluates as null.

The result is that, in your code, Object.GetType() is seeing a boxed int value when it executes, not a boxed Nullable<int> object (because, again, that's impossible). This is why the name of a nullable is the same as the name of its content. This is the simplest way to demonstrate what's happening:

new Nullable<int>(123).GetType() == typeof(int)
new Nullable<int>(123).GetType() != typeof(Nullable<int>)

As a side note, because a nullable without a value boxes as null, it's an error to invoke .GetType() on a null nullable! This simultaneously makes sense (it's null, right?) and doesn't make sense (it's a value type... it can't really be null!). When a nullable has no value, you can invoke methods implemented or overridden on Nullable itself (because these calls do not require boxing), but you cannot invoke methods inherited from Object and not overridden.

Nullable has a strange dual personality, and sometimes it results in surprises like this.

Now that we know what's going on with the Nullable case, we can see that Nullable doesn't actually rename itself -- the name of the type that you see is the result of nullable boxing behavior.

cdhowie
  • 158,093
  • 24
  • 286
  • 300