为什么Nullable <T>可以为空?为何无法复制?

Gui*_*ume 5 c# nullable

当我写作

Nullable<Nullable<DateTime>> test = null;

我收到编译错误:

The type 'System.Datetime?' must be a non-nullable value type in order to use it as a paramreter 'T' in the generic type or method 'System.Nullable<T>'

Nullable<T>它是struct如此,它应该是不可空的.

所以我试着创建这个struct:

public struct Foo<T> where T : struct
{
    private T value;

    public Foo(T value)
    {
        this.value = value;
    }

    public static explicit operator Foo<T>(T? value)
    {
        return new Foo<T>(value.Value);
    }

    public static implicit operator T?(Foo<T> value)
    {
        return new Nullable<T>(value.value);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我写的时候

        Nullable<Foo<DateTime>> test1 = null;
        Foo<Nullable<DateTime>> test2 = null;
        Foo<DateTime> test3 = null;
Run Code Online (Sandbox Code Playgroud)

第一行是好的,但对于第二行和第三行,我得到以下两个编译错误:

The type 'System.DateTime?' must be a non-nullable value type in order to use it as a parameter 'T' in the generic type or method 'MyProject.Foo<T>' (仅限第二行)

Cannot convert null to 'MyProject.Foo<System.DateTime?> because it is a non-nullable value type'

        Foo<Nullable<DateTime>> test = new Foo<DateTime?>();
Run Code Online (Sandbox Code Playgroud)

如果Nullable<DateTime>是a,则不会发生任何事件struct.

从概念上讲,我可以理解为什么可以Nullable<T>为空,它可以避免有类似的东西,DateTime??????????但我仍然可以List<List<List<List<List<DateTime>>>>>......

那么为什么这个限制以及为什么我不能重现这种行为Foo<T>呢?这个限制是由编译器强制执行的还是Nullable<T>代码中固有的?

我读过这个问题,但它只是说不可能没有任何答案从根本上说明为什么它不可能.

O. *_*per 10

但是Nullable是一个结构,所以它应该是不可为空的.

Nullable<T>确实是一个结构,但文档中所述的通用struct约束的确切含义是:

type参数必须是值类型.除了Nullable可以指定的任何值类型.有关更多信息,请参阅使用可空类型(C#编程指南).

出于同样的原因,你的路线

Foo<Nullable<DateTime>> test2 = null;
Run Code Online (Sandbox Code Playgroud)

导致您看到的编译器错误,因为您的泛型struct约束T以某种方式限制您的泛型参数,因此Nullable<DateTime>不能将其指定为实际参数.

对此的理由可能是打电话,如

Nullable<Nullable<DateTime>> test = null;
Run Code Online (Sandbox Code Playgroud)

更加明确:这是否意味着您要设置test.HasValuefalse,还是你确实要设置test.HasValuetruetest.Value.HasValuefalse?由于对非可空类型参数的给定限制,不会发生这种混淆.

最后,null赋值的工作Nullable<T>原因是 - 正如所选答案及其对这个SO问题SO问题的评论所暗示的那样- 该Nullable<T>类型由一些编译器魔法支持.