Nullable <T>混乱

10 c# generics nullable

为什么禁止以下内容?

Nullable<Nullable<int>>
Run Code Online (Sandbox Code Playgroud)

struct MyNullable <T>
{


}

MyNullable<Nullable<int>> 
Run Code Online (Sandbox Code Playgroud)

不是

Shu*_*oUk 19

这是因为struct约束实际上意味着'不可为空',因为Nullable尽管是一个结构体,但是可以为空(可以接受值null),Nullable<int>它不是外部Nullable的有效类型参数.

这在约束文档中明确说明

其中T:struct
类型参数必须是值类型.可以指定除Nullable之外的任何值类型.
有关更多信息,请参阅使用可空类型(C#编程指南).

如果你想要它的基本原理,你需要实际的语言设计师对它的评论,我找不到.但是我会假设:

  1. 以其当前形式实现Nullable所需的编译器和平台更改是相当广泛的(并且是2.0版本的相对最后一分钟添加).
  2. 他们有几个可能令人困惑的边缘情况.

允许相当于int ?? 只会混淆,因为语言无法区分Nullable <Nullable<null>>和Nullable,<null>也没有任何明显的解决方案.

Nullable<Nullable<int>> x = null;
Nullable<int> y = null;
Console.WriteLine(x == null); // true
Console.WriteLine(y == null); // true
Console.WriteLine(x == y); // false or a compile time error!
Run Code Online (Sandbox Code Playgroud)

使该返回为真将是涉及Nullable类型的许多操作的非常复杂和显着的开销.

CLR中的某些类型是"特殊的",示例是字符串和基元,因为编译器和运行时对彼此使用的实现有很多了解.Nullable也是这样特别的.由于它已经在其他领域特殊套管特殊套管where T : struct方面没有这么大的优势.这样做的好处是处理泛型类中的结构,因为除了Nullable之外,它们都不能与null进行比较.这意味着jit总是可以安全地认为t == null是假的.

如果语言被设计为允许两个非常不同的概念进行交互,则往往会产生奇怪,混乱或向下的危险边缘情况.作为一个例子,考虑Nullable和相等运算符

int? x = null;
int? y = null;
Console.WriteLine(x == y); // true
Console.WriteLine(x >= y); // false!     
Run Code Online (Sandbox Code Playgroud)

通过在使用struct泛型约束时阻止Nullables,可以避免许多令人讨厌(和不清楚)的边缘情况.

至于规范的确切部分,从第25.7节(强调我的)强制要求:

值类型约束指定用于type参数的类型参数必须是值类型(第25.7.1节).具有值类型约束的任何非可空结构类型,枚举类型或类型参数都满足此约束.具有值类型约束的类型参数也不应具有构造函数约束.System.Nullable类型指定T的非可空值类型约束. 因此,递归构造的形式类型T ?? 和Nullable <Nullable <T >>是禁止的.


rec*_*ive 14

我相信你只能在Nullables中使用不可为空的值类型.由于Nullable它本身可以为空,因此禁止以这种方式嵌套.

来自http://msdn.microsoft.com/en-us/library/kwxxazwb.aspx

public Nullable(
    T value
)
Run Code Online (Sandbox Code Playgroud)

类型:TA值类型.