当 T 被限制为枚举时,为什么 return default(T?) 不给出 null?

Tor*_*mod 13 .net c#

我有一个解析器,可以将文本文件渲染到数据模型中。有些字段是可选的,在模型中将表示为 null。

然而,一个奇怪的行为让我头疼。当我具体处理可为空时,它的行为符合预期。

Foo? a = null;
Run Code Online (Sandbox Code Playgroud)

...工作得很好。

Foo? b = default(Foo?);
Run Code Online (Sandbox Code Playgroud)

...工作也很好。b 为空。

然而,每当我将其包装在泛型类中时,似乎很难以相同的方式处理泛型类型参数。

void Main()
{
    Foo? is_null = null;
    Foo? is_also_null = default (Foo?);

    Foo? does_not_work = FooClass.GetNull<Foo>();
    Foo? is_not_null = FooClass.GetDefault<Foo>();   // Should be null, AFAICT, but isn't,
    
}

public static class FooClass
{
    public static T? GetNull<T>() where T:System.Enum
    {
        return null;  //Compile error: CS0403 Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
    }
    public static T? GetDefault<T>() where T : System.Enum
    {
        return default(T?); // Why does this not return null? Shouldn't this be the same as default(Foo?) ?
    }
}

public enum Foo
{
    one,two,three
}
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?或者我在这里缺少什么?

Mar*_*ell 18

枚举约束基本上是:不按您的预期工作;这T : Enum并不意味着它将其视为基元- 而是将其视为装箱值(对象),而它恰好是该类型的子类型Enum(或其Enum本身!)。强调:请记住您可以GetDefault<Enum>在此处使用。

如果T?没有支持Nullable Reference Types 的编译器,并且在 NRT 支持和禁用 NRT 的情况下,甚至无法编译:它会给你一个 CS8632 警告;这意味着T?这里指的是 NRT,而不是 Nullable<T>。您可以通过添加 来解决此问题T : struct, Enum,但如果没有:default(T?)则与default(T)(因为?for NRTs 不会更改类型语义 - 只是无论我们是否期望空值)相同,并且default(T)是零枚举。