为什么我不能写Nullable <Nullable >?
Nullable
的定义是:
[SerializableAttribute] public struct Nullable where T : struct, new()
where T : struct
意味着T
只能是值类型的约束。 所以我很清楚我不能写:
Nullable a; //error. makes sense to me
因为string
是引用类型,而不是值类型。 但我真的不明白为什么我不能写
Nullable<Nullable> b; //error. but why?
为什么不允许? 毕竟, Nullable
是一个值类型,因此,它可以是Nullablle
类型参数。
当我在ideone上编译它时,它会出现此错误( ideone ):
错误CS0453:类型’int?’ 必须是非可空值类型才能在generics类型或方法’System.Nullable’中将其用作类型参数’T’编译失败:1个错误,0个警告
从C#语言规范的4.1.10节:
相反, 非可空值类型是
System.Nullable
以外的任何值类型及其简写T?
(对于任何T
),加上任何被约束为非可空值类型的类型参数(即具有struct
约束的任何类型参数)。System.Nullable
类型指定T
(第10.1.5节)的值类型约束,这意味着可空类型的基础类型可以是任何不可为空的值类型。 可空类型的基础类型不能是可空类型或引用类型。 例如,int??
和string?
是无效的类型。
因为它在C#规范中(第4.4.4节):
如果约束是值类型约束(struct),则类型A必须满足以下条件之一:
- A是结构类型或枚举类型, 但不是可空类型 。 请注意,System.ValueType和System.Enum是不满足此约束的引用类型。
- A是具有值类型约束(第10.1.5节)的类型参数。
来自C#4规范的§10.1.5:
值类型约束指定用于type参数的类型参数必须是非可空值类型。 具有值类型约束的所有非可空结构类型,枚举类型和类型参数都满足此约束。 请注意,虽然归类为值类型,但可空类型(第4.1.10节)不满足值类型约束。 具有值类型约束的类型参数也不能具有构造函数约束。
正如其他人所说,该规范禁止这样做。
深入挖掘,值得认识到你可以创建自己的结构来允许这种模式:
struct Nestable where T : struct { /* ... */ } new Nestable>(); // This works just fine
禁止使用嵌套的nullables不能使用您和我可用的类型系统来表达。 它仅由编译器(CS0453)中的特殊情况强制执行。
旁白:问题中显示的new()
约束实际上并不存在于System.Nullable
。 使用struct
约束时禁止new()
约束。
CS0451:’new()’约束不能与’struct’约束一起使用
无论如何,所有结构都支持默认初始化。
这不是一个答案,而只是思考的问题。
第1轮
Nullable
错误CS0453:类型’int?’ 必须是不可为空的值类型才能在generics类型或方法’Nullable’中将其用作参数’T’
智能感知提示…… 名称可以简化
第2轮
Nullable
a;
错误CS0453:类型’int?’ 必须是不可为空的值类型才能在generics类型或方法’Nullable’中将其用作参数’T’
智能感知提示…… 名称可以简化
第3轮
int?? a;
错误CS1519:无效的令牌’??’ 在类,结构或接口成员声明中
错误CS1525:无效的表达式术语’??’
结论
int?
基本上只是对Nullable
的简短评估,但是没有int??
这样的东西int??
这是我在短手中看到代表Nullable
的唯一方法。 加上int??
借用零合并算子,所以我很高兴它不可能,因为它看起来很可怕。 想象一下int????????????? a;
int????????????? a;
多么无意义。
最后,由于Nullable的引用源没有产生任何强制执行的约束,我的猜测是当Cul中引入了可空值类型时,这个约束被作为特殊情况引入CLR。