C# 为什么可以';类型不能用作常量值吗?
引述: 常量表达式是可以在编译时完全计算的表达式。因此,引用类型常量的唯一可能值是字符串和空引用 根据:,C# 为什么可以';类型不能用作常量值吗?,c#,.net,types,reference,constants,C#,.net,Types,Reference,Constants,引述: 常量表达式是可以在编译时完全计算的表达式。因此,引用类型常量的唯一可能值是字符串和空引用 根据:,typeof(T)是一个编译时表达式 那么为什么类型不能是常量呢 以下代码将不会编译: public const Type INT_TYPE = typeof(int); 上述代码无法编译的原因正是MSDN所述的原因-无法在编译应用程序时确定常量的值。使用typeof(int)需要在运行时确定常量的值。理论上,.NET可以允许编译上述语句,但从严格意义上讲,它不是一个常量。编译器在生成的I
typeof(T)
是一个编译时表达式
那么为什么类型不能是常量呢
以下代码将不会编译:
public const Type INT_TYPE = typeof(int);
上述代码无法编译的原因正是MSDN所述的原因-无法在编译应用程序时确定常量的值。使用typeof(int)需要在运行时确定常量的值。理论上,.NET可以允许编译上述语句,但从严格意义上讲,它不是一个常量。编译器在生成的IL代码中用文本值替换常量。但是typeof
是一个方法调用:
typeof(int);
// Becomes:
L_0000: ldtoken int32
L_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
发件人:
常量可以是数字、布尔值、字符串或空引用
常量基本上仅限于可在编译类型下表示为二进制值的原语值(因为编译时它被“注入”到客户机代码中)。由于Type
是一个具有多个属性的类,因此没有简单的二进制表示可以“烘焙”到客户机代码中。至少在某些情况下,C#编译器和IL肯定支持将类型作为常量表达式。看看属性,它们经常使用这一点:
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
如果检查二进制数据,您会注意到这是完全限定的类名,没有任何程序集标识(System.Collections.Generic.Mscorlib_CollectionDebugView`1)
回答你的问题:我看不出有任何技术上的理由说明这是不可能的,由于没有序列化程序集引用,因此声明此类型的DLL仍然可以更新,而不会影响以前编译的引用它的类型。因此,我也无法想象兼容性考虑因素会阻止它。是对对象的运行时引用。直到运行时才知道TypeInfo对象将驻留在何处。我想知道是什么让你问这个问题,你肯定不会在实际代码中使用这样的常量吗?为此,我使用静态只读。为什么编译时不知道typeof(int)
?因为你可以为AnyCPU
和typeof(int)编译代码
在不同的体系结构上会有所不同<代码>类型
是对类型的运行时引用,而不是编译时常量。@jwdonahue,不是true。只有指针和引用类型的大小会改变,这可能是由运行的框架(32位或64位)决定的。@MattChamberstypeof(int)!=sizeof(int)
。typeof(int)
返回的Type
的实际值可能因系统而异。我想不出为什么它不能在同一个盒子上从一个运行时切换到另一个运行时<代码>类型类型的特定实例是在运行时而不是编译时派生的。那么,如果大小不一样,为什么结果的类型需要不同呢?也就是说,为什么不是常数?
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
.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
)