基本上为什么C#中的以下内容无效?我可以找到很多好的用途,实际上可以通过创建我自己的可空结构类来修复它,但是为什么以及C#规范(以及编译器)如何阻止它呢?
以下是我所说的部分例子。
struct MyNullable<T> where T : struct
{
public T Value;
public bool HasValue;
// Need to overide equals, as well as provide static implicit/explit cast operators
}
class Program
{
static void Main(string[] args)
{
// Compiles fine and works as expected
MyNullable<Double> NullableDoubleTest;
NullableDoubleTest.Value = 63.0;
// Also compiles fine and works as expected
MyNullable<MyNullable<Double>> NullableNullableTest;
NullableNullableTest.Value.Value = 63.0;
// Fails to compile...despite Nullable being a struct
// Error: The type 'double?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'ConsoleApplication1.MyNullable<T>'
MyNullable<Nullable<Double>> MyNullableSuperStruct;
}
}
答案 0 :(得分:8)
这是struct
。它只是不满足值类型泛型类型参数约束。从语言规范的10.1.5开始:
值类型约束指定用于type参数的类型参数必须是非可空值类型。具有值类型约束的所有非可空结构类型,枚举类型和类型参数都满足此约束。请注意,虽然归类为值类型,但可空类型(第4.1.10节)不满足值类型约束。
所以,where T : struct
并不意味着你的意思。
基本上为什么C#中的以下内容无效?
因为where T : struct
只能由T
满足不可为空的值类型。 Nullable<TNonNullableValueType>
不满足此约束条件。
编译器为什么以及如何阻止它?
为什么呢?符合规范。怎么样?通过执行语法和语义分析并确定您提供了不满足泛型类型约束T
的泛型类型参数where T : struct
。
[我]可以通过创建我自己的可空结构类来修复它,但是
不,你的版本没有修复它。它基本上与Nullable<T>
完全相同,除非您没有得到编译器的特殊处理,并且您将导致编译器实现不会打包的装箱。
我可以找到很多好的用途
真的?如?请注意,Nullable<T>
的基本思想是拥有一个可以包含T
的存储位置,或者可以表示“缺少值”。嵌套这个有什么意义?那就是Nullable<Nullable<T>>
的重点是什么?它甚至没有概念意义。这可能就是它被禁止的原因,但我只是在猜测( Eric Lippert confirmed这个推测是正确的)。例如,什么是int??
?它表示一个存储位置,表示缺少值或是int?
,它本身就是一个存储位置,表示缺少值或是int
?有什么用?
答案 1 :(得分:2)
struct constraint的拨号为nullables的一个原因是我们希望能够在泛型方法中使用T?
。如果struct
允许可以为空的值类型,则编译器必须禁止T?
。
在其他情况下,可空类型必须在编译器中进行特殊处理:
??
运算符一起使用;不可取之不。