为什么禁止以下内容?
Nullable<Nullable<int>>
而
struct MyNullable <T>
{
}
MyNullable<Nullable<int>>
不是
答案 0 :(得分:19)
这是因为struct约束实际上意味着'not nullable',因为Nullable尽管是一个结构体,但是可以为空(可以接受值null)Nullable<int>
不是外部Nullable的有效类型参数。
这在the constraints documentation
中已明确说明其中T:struct
type参数必须是值类型。可以指定除Nullable之外的任何值类型 有关详细信息,请参阅使用可空类型(C#编程指南)。
如果你想要的理由,你需要实际的语言设计师对它的评论,我找不到。但是我会假设:
允许相当于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)结构支持 仅使用值类型作为可空值 类型,因为引用类型是 可设计的。