2015-08-25 3 views
11

Цитирование MSDN - const (C# reference):Почему нельзя использовать тип как постоянное значение?

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

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

Так почему же нельзя Type быть постоянным значением?

Следующий код не будет компиляции:

public const Type INT_TYPE = typeof(int); 
+0

Интересно, что заставляет вас задавать этот вопрос, конечно, вы бы не использовали такую ​​константу в реальном коде? – MarioDS

+0

Для этой цели вместо этого я использую static readonly. –

ответ

5

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

typeof(int); 

// Becomes: 
L_0000: ldtoken int32 
L_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) 
0
public const Type INT_TYPE = typeof(int); 

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

2

От MSDN:

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

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

1

Компилятор C# и 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, объявляющая этот тип, все еще может быть обновлена не затрагивая ранее скомпилированный тип, ссылающийся на него.

Смежные вопросы