C# 为什么可以';我写的是可为空的<;可为空<;int>>;?

C# 为什么可以';我写的是可为空的<;可为空<;int>>;?,c#,nullable,value-type,C#,Nullable,Value Type,定义如下: 因为string是引用类型,而不是值类型。但我真的不明白为什么我不能写 Nullable<Nullable<int>> b; //error. but why? Nullable b//错误。但是为什么呢? 为什么不允许呢?毕竟,Nullable是一种值类型,因此,它可以是Nullable的类型参数 当我在ideone上编译它时,它给出了以下错误(): 错误CS0453:类型“int”必须是不可为null的值类型,才能将其用作泛型类型或方法“System.

定义如下:

因为
string
是引用类型,而不是值类型。但我真的不明白为什么我不能写

Nullable<Nullable<int>> b; //error. but why?
Nullable b//错误。但是为什么呢?
为什么不允许呢?毕竟,
Nullable
是一种值类型,因此,它可以是
Nullable
的类型参数

当我在ideone上编译它时,它给出了以下错误():

错误CS0453:类型“int”必须是不可为null的值类型,才能将其用作泛型类型或方法“System.nullable”中的类型参数“T” 编译失败:1个错误,0个警告

因为它在C#规范(第4.4.4节)中:

如果约束是值类型约束(struct),则类型A必须满足以下条件之一:

  • 是结构类型或枚举类型,但不是可为null的类型。请注意,System.ValueType和System.Enum是不满足此约束的引用类型
  • A是具有值类型约束的类型参数(§10.1.5)

根据C语言规范第4.1.10节:

不可为空的值类型反过来说是除
系统之外的任何值类型。可为空的
及其缩写
T?
(对于任何
T
),加上任何被约束为不可为空的值类型的类型参数(即具有
结构
约束的任何类型参数)。
System.Nullable
类型指定了
T
(§10.1.5)的值类型约束,这意味着可为null类型的基础类型可以是任何不可为null的值类型。可空类型的基础类型不能是可空类型或引用类型。例如,
int???
string?
是无效类型

根据C#4规范§10.1.5:

值类型约束指定用于类型参数的类型参数必须是不可为null的值类型。具有值类型约束的所有不可为null的结构类型、枚举类型和类型参数都满足此约束。请注意,尽管分类为值类型,但可空类型(§4.1.10)不满足值类型约束。具有值类型约束的类型参数不能同时具有构造函数约束


正如其他人所说,规范禁止这样做

深入挖掘,值得认识到,您可以创建自己的结构来支持此模式:

struct Nestable<T> where T : struct { /* ... */ }

new Nestable<Nestable<int>>(); // This works just fine
struct可嵌套,其中T:struct{/*…*/}
新的Nestable();//这个很好用
不能使用您和我可用的类型系统来表示禁止嵌套Nullable。它仅由编译器(CS0453)中的特殊情况强制执行


旁白:问题中显示的
new()<使用
struct
约束时,禁止使用code>new()
约束

CS0451:“new()”约束不能与“struct”约束一起使用


无论如何,所有结构都支持默认初始化。

这不是一个确切的答案,但值得思考

第一轮

可为空a

错误CS0453:类型“int”必须是不可为Null的值类型,才能将其用作泛型类型或方法“nullable”中的参数“T”

智能感知提示。。。 名称可以简化


第二轮

Nullable
a

错误CS0453:类型“int”必须是不可为Null的值类型,才能将其用作泛型类型或方法“nullable”中的参数“T”

智能感知提示。。。 名称可以简化


第三轮

int??a

错误CS1519:类、结构或接口成员声明中的令牌“??”无效

错误CS1525:无效的表达式项“??”


结论

int?
本质上只是对
Nullable
的一个简单的评估,但是没有
int???
这样的东西,这是我所能看到的用简单的方式表示
Nullable
。Plus
int???
借用了空合并操作符,所以我很高兴这不可能,因为它看起来很糟糕。想象一下
int?????????????a多么没有意义


最后,由于的引用源不产生任何强制执行该约束的约束,因此我猜想该约束是在C#中引入可空值类型时作为特例烘焙到CLR中的。

对不起,我的答案是错误的。语句
newnullable()
编译(产生一个值为null的
int?
),尽管默认构造函数没有文档记录。是的,答案是当您尝试编译代码时应该得到的错误。@rudolf\u franek:不管这意味着什么,但我的重点是类型约束,不是关于代码的语义含义。@rudolf\u franek:正如我所说的,我关注的是约束类型,根据它,代码应该编译,即使它在语义上没有意义。@rudolf\u franek:对不起。您的评论无助于理解此处的语言。请详细说明规范报价。我不完全明白这一点。我是C#新手。应用于类的
struct
泛型类型约束被指定为“除
Nullable
之外的所有值和枚举类型”,专门用于停止这种循环。@thecoop:这不是一个奇点。如果没有
struct
Nullable
的类型参数的约束,可以使用
字典
包含方法
Nullable
TryGetValue(TKey)`而不必使用
out
参数。给定
字典myDict
,在
var之后,it=myDict.TryGetValue(“Fred”)
如果
it.HasValue
为false,则表示未找到任何键;如果
it.HasValue
为真,但
it.V
Nullable<Nullable<int>> b; //error. but why?
struct Nestable<T> where T : struct { /* ... */ }

new Nestable<Nestable<int>>(); // This works just fine