Почему нельзя использовать тип как постоянное значение?

Цитата MSDN - const (ссылка на С#):

Постоянное выражение - это выражение, которое может быть полностью оценено во время компиляции. Поэтому единственными возможными значениями констант ссылочных типов являются строка и нуль.

В соответствии с выражением typeof (T) и Object.GetType() typeof(T) - это выражение времени компиляции.

Итак, почему нельзя < <21 > быть постоянным значением?

Следующий код не будет компилироваться:

public const Type INT_TYPE = typeof(int);

Ответ 1

Константы заменяются компилятором буквальными значениями в полученном IL-коде. Но typeof - вызов метода:

typeof(int);

// Becomes:
L_0000: ldtoken int32
L_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)

Ответ 2

Из MSDN:

Константы могут быть числами, булевыми значениями, строками или нулевой ссылкой.

Константы в основном ограничены примитивными значениями, которые могут быть представлены как двоичное значение в compile-type (поскольку он "впрыскивается" в код клиента при компиляции). Поскольку Type - это класс, который имеет несколько свойств, нет простого двоичного представления, которое может быть "запечено" в клиентском коде.

Ответ 3

Компилятор С# и IL, безусловно, поддерживают типы как постоянные выражения, по крайней мере в определенных ситуациях. Посмотрите на атрибуты, они много используют:

[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]

Тип встроен как строка в сгенерированном компилятором коде, выше строки компилируется в следующий код IL:

.custom instance void System.Diagnostics.DebuggerTypeProxyAttribute::.ctor(class System.Type) = (
    01 00 39 53 79 73 74 65 6d 2e 43 6f 6c 6c 65 63
    74 69 6f 6e 73 2e 47 65 6e 65 72 69 63 2e 4d 73
    63 6f 72 6c 69 62 5f 43 6f 6c 6c 65 63 74 69 6f
    6e 44 65 62 75 67 56 69 65 77 60 31 00 00
)

Если вы проверите двоичные данные, вы заметите, что это полное имя класса без какой-либо идентификации сборки (System.Collections.Generic.Mscorlib_CollectionDebugView`1).

Чтобы ответить на ваш вопрос: я не вижу никаких технических причин, почему это не должно быть возможным, и я не могу представить соображения совместимости, которые его предотвращают, поскольку сериализация сериальной ссылки отсутствует, поэтому DLL, объявляющая этот тип, все еще может быть обновлена ​​без влияя на ранее скомпилированный тип, ссылающийся на него.

Ответ 4

public const Type INT_TYPE = typeof(int);

Причина, по которой этот код не будет компилироваться, - это точная причина, указанная MSDN. Значение константы не может быть определено на момент компиляции приложения. Использование typeof (int) требует определения значения константы во время выполнения. Теоретически .NET мог бы позволить вышеприведенное выражение компилировать, но тогда оно не будет константой в строгом смысле этого слова.