可空的<t>混淆</t>

时间:2009-03-01 17:07:19

标签: c# generics nullable

为什么禁止以下内容?

Nullable<Nullable<int>>

struct MyNullable <T>
{


}

MyNullable<Nullable<int>> 

不是

5 个答案:

答案 0 :(得分:19)

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

这在the constraints documentation

中已明确说明
  

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

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

  1. 以其当前形式实现Nullable所需的编译器和平台更改非常广泛(并且是2.0版本的相对最后一分钟添加)。
  2. 他们有几个可能令人困惑的边缘情况。
  3. 允许相当于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!
    

    使得该返回为true将是涉及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!     
    

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

    关于规范from section 25.7(强调我的)的规范的确切部分:

      

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

答案 1 :(得分:14)

我相信你只能在Nullable中使用不可为空的值类型。由于Nullable本身可以为空,因此禁止嵌套。

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

public Nullable(
    T value
)
     

类型:T值类型。

答案 2 :(得分:3)

Nullable很特别,因为明确支持CLR内置的Nullable类型的装箱和拆箱:

如果对box使用MSIL Nullable<T>指令,则实际上会得到null作为结果。没有其他值类型在装箱时会产生空值。

对拆箱有类似和对称的支持。

答案 3 :(得分:2)

Nullable的泛型类型参数本身必须是非可空类型(即值类型)。这是我得到的C#编译器警告,它似乎有意义。告诉我,你为什么要做这样的事呢?我个人认为没有用,甚至对这样的宣言没什么意义。

答案 4 :(得分:0)

Nullable允许您获取值类型并使其类似于引用类型,因为值存在与否(为空)。由于引用类型已经可以为空,因此不允许使用。

引自MSDN

  

Nullable(T)结构支持   仅使用值类型作为可空值   类型,因为引用类型是   可设计的。