为什么可以';t a类型用作常数值

本文关键字:类型 常数值 为什么 | 更新日期: 2023-09-27 18:09:44

引用MSDN-const(C#引用(:

常量表达式是可以在编译时完全求值的表达式。因此,引用类型的常量的唯一可能值是stringnull引用。

根据:typeof(T(vs.Object.GetType((的性能,typeof(T)是一个编译时表达式。

那么,为什么Type不能是一个常数值呢?

以下代码将不会编译

public const Type INT_TYPE = typeof(int);

为什么可以';t a类型用作常数值

编译器在生成的IL代码中用文字值替换常量。但是typeof是一个方法调用:

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

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仍然可以更新,而不会影响引用它的先前编译的类型。

来自MSDN:

常量可以是数字、布尔值、字符串或null引用。

常量基本上局限于可以在编译类型中表示为二进制值的基元值(因为它在编译时被"注入"到客户端代码中(。由于Type是一个具有多个属性的,因此没有一个简单的二进制表示可以"烘焙"到客户端代码中。

Type是对TypeInfo对象的运行时引用。直到运行时才知道TypeInfo对象将驻留在哪里。

public const Type INT_TYPE = typeof(int);

上面的代码不会编译的原因正是MSDN所说的原因——在编译应用程序时无法确定常量的值。使用typeof(int(需要在运行时确定常量的值。理论上,.NET可以允许编译上面的语句,但从严格意义上讲,它不是一个常量。