为什么&#39; struct Nullable <t>&#39;不是结构?</t>

时间:2012-04-17 18:05:53

标签: c# struct nullable

基本上为什么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;
    }
}

2 个答案:

答案 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?

在其他情况下,可空类型必须在编译器中进行特殊处理:

  • null关键字必须可以隐式转换为可空类型;对于值类型,这是不可能的。
  • 可以将Nullable值类型与null关键字进行比较;如果使用不可为空的值类型,则此比较始终返回false。
  • 可以为空的值类型与??运算符一起使用;不可取之不。