匹配参数的可空性和返回类型的泛型类型参数

Şaf*_*Gür 8 c# .net-core c#-8.0 nullable-reference-types .net-core-3.0

public readonly struct Foo<T>
{
    // ...
    public T Value { get; }
}

public static Foo<string?> Bar(Foo<string?> foo)
{
    if (foo.Value is null) { /* Something */ }
    else { /* Some other thing */ }
    return foo;
}

public static void Main()
{
    var foo1 = new Foo<string>("s");
    var ret1 = Bar(foo1); // Warns because foo1's type parameter is not nullable

    var foo2 = new Foo<string?>("s");
    var ret2 = Bar(foo2); // Ok because foo2's type parameter is nullable
}
Run Code Online (Sandbox Code Playgroud)
  • 我可以写 Bar 来接受Foo<string?>Foo<string>吗?
  • 我可以注释 Bar 来指定“进出的东西”,因此T返回的Foo<T>可空性T将与参数的可空性相同Foo<T>吗?

Şaf*_*Gür 1

对于Foo<string?> Bar(Foo<string?> foo)方法来说,接受的 foo 的类型参数与返回的 foo 的类型参数没有关系。目前,还没有办法注释它们的可空性的预期关系。

T然而,泛型方法中的类型参数Foo<T> Bar<T>(Foo<T> foo)允许我们共享可空性,并且我们可以添加泛型类型约束,where T : MyType?以便使用特定于类型的功能。

不幸的是,我们不能写where T : string?,因为 C# 不允许将密封类用作类型约束。这是合理的,因为它以前没有意义 - 如果我们只能使用一种类型,为什么我们首先将方法设计为通用方法呢?好吧,随着 C# 8 和可空引用类型的出现,我想我们现在可能有一个合理的理由了。也许团队可以像取消枚举一样取消此限制。

回答我自己的问题:

  • 没有属性来注释此用例。
  • 泛型可以与类型约束一起使用,但只能与未密封的类型一起使用。

附带说明:尽管 C# 不允许我们使用密封类型作为类型约束,但 IL 允许。因此,如果编织是一种选择,我们实际上可以向泛型类型参数添加密封类型约束。可以扩展ExtraConstraints这样的解决方案来提供此功能。