Ответ 1
Тест не работает, потому что:
Вызов GetType по типу Nullable вызывает операцию бокса, когда тип неявно преобразован в Object. Поэтому GetType всегда возвращает объект Тип, который представляет базовый тип, а не тип Nullable.
Вы можете узнать больше из Как идентифицировать нулевой тип.
Некоторые примеры, взятые из предыдущей статьи:
int? i = 5;
Type t = i.GetType();
Console.WriteLine(t.FullName); //"System.Int32"
Также обратите внимание:
Оператор С# is также работает с базовым типом Nullable. Поэтому вы не можете использовать , чтобы определить, является ли переменная типом Nullable. В следующем примере показано, что оператор рассматривает Nullable <int> переменная как int.
int? i = 5;
if (i is int) { ... } // true
Вы правы, полагая, что компилятор С# оптимизирует типы с нулевым значением. Здесь цитата из Jon Skeet С# в глубине, которая должна ответить на ваш вопрос:
Только для бокса и распаковки, которые CLR имеет любое особое поведение в отношении типов с нулевым значением. Фактически, поведение было изменено незадолго до выпуска .NET 2.0 в результате запросов сообщества.
Экземпляр Nullable помещается в поле для нулевой ссылки (если она не имеет значения) или значение в коробке T (если оно есть). Он никогда не привязывается к "коробке с нулевым значением int" - нет такого типа.
Есть аналогичный поток в StackOverflow: Тип Nullable не является нулевым типом?