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

Posted

技术标签:

【中文标题】匹配参数的可空性和返回类型的泛型类型参数【英文标题】:Matching nullability of argument and return type's generic type parameters 【发布时间】:2020-02-06 14:02:13 【问题描述】:
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

我可以写 Bar 来接受 Foo&lt;string?&gt;Foo&lt;string&gt; 吗? 我可以注释Bar来指定“什么进去就出去”,所以返回的Foo&lt;T&gt;T的可空性将与参数Foo&lt;T&gt;T的可空性相同?李>

【问题讨论】:

有很多属性可以让你注释一些依赖,但不是全部。基本上,它的目的不是解决所有可空性问题,只是解决大部分问题。 例如,您可以设置一个依赖项,说明“如果使用非空引用调用此方法调用的结果将不为空”,但您不能将其嵌套在类型,只有值。我建议创建两个重载并重命名其中一个,可能使用 TryXYZ 方法名称前缀。 Bar 也像public static Foo&lt;T&gt; Bar&lt;T&gt;(Foo&lt;T&gt; foo) 一样通用怎么样? sharplab.io/… 如果该方法只应该采用Foo&lt;string&gt;(可空或不可空),那么这会产生它自己的问题,您现在有一个采用Foo&lt;anything&gt;的方法并且必须处理那个。 @Lasse - 是的,我找不到允许我对此进行注释的人,我担心没有办法。你建议有两种不同的方法肯定会奏效,但它真的很难看。是的,对于这种方法来说,null 是有效的,我会处理它。 【参考方案1】:

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

但是,在泛型 Foo&lt;T&gt; Bar&lt;T&gt;(Foo&lt;T&gt; foo) 方法中输入参数 T 将允许我们共享可空性,并且我们可以添加像 where T : MyType? 这样的泛型类型约束以使用特定于类型的功能。

很遗憾,我们不能写where T : string?,因为C# 不允许将密封类用作类型约束。这是合理的,因为它以前没有意义 - 如果我们只能使用一种类型,为什么我们首先要将方法设计为泛型?好吧,随着 C# 8 和可空引用类型的出现,我认为我们现在可能有一个正当的理由。也许团队可以解除这个限制,因为他们解除了枚举的限制。

回答我自己的问题:

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

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

【讨论】:

以上是关于匹配参数的可空性和返回类型的泛型类型参数的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中的泛型类是啥东西?

17.scala的泛型类

怎么取出类的泛型类型

Java中的泛型

如何获取java泛型的参数类型

泛型类的基本使用