[英]where t : class generic constraint and const value declaration
根据10.4 Constants
C#规范:
常量声明中指定的类型必须是 sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal,bool,string,enum-type 或reference-type。 每个常量表达式必须生成目标类型或可通过隐式转换(第6.1节)转换为目标类型的类型的值。
为什么我不能做以下事情:
public class GenericClass<T>
where T : class
{
public const T val = null;
}
这应该是可能的,因为:
where T : class
表示, The type argument must be a reference type; this applies also to any class, interface, delegate, or array type
The type argument must be a reference type; this applies also to any class, interface, delegate, or array type
(来自MSDN ) string
之外,引用类型常量的唯一可能值为null
。 任何可能的解释?
可能的解释
考虑CLR如何初始化泛型类的static
成员,或者在泛型类型上调用静态构造函数时。 通常,首次加载程序时会发生静态初始化; 但是,泛型类在第一次创建该类的实例时初始化其静态成员。
请记住,泛型类不是单一类型; 在类型声明中传递的每个T
都在创建一个新类型。
现在考虑一个const
表达式,它需要在编译时进行求值。 尽管T被约束为一个类,因此它可以接收值null,但是在运行时创建类之前,变量val
不存在于内存中。
例如,考虑const T val
是否有效。 然后我们可以使用代码中的其他地方:
GenericClass<string>.val
GenericClass<object>.val
编辑
虽然两个表达式的值都为null
,但前者的类型为string
,后者的类型为object
。 为了使编译器执行替换,它需要知道有问题的常量的类型定义。
约束可以在编译时强制执行,但是开放泛型在运行时之前不会转换为封闭的泛型。 因此, GenericClass<object>.val
不能存储在编译器的本地内存中以执行替换,因为编译器没有实例化泛型类的闭合形式,因此不知道将常量表达式实例化的类型。
Eric Lippert承认这是一个bug,应该允许:
它看起来像你发现了一个错误; 要么bug在规范中,应该明确地调出类型参数不是有效类型,或者bug在编译器中,应该允许它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.