什么是C#8中的未知可空性?

Sti*_*gar 11 c# c#-8.0 nullable-reference-types

在C#8.0中,我们可以有可为空的引用类型。文档指出存在4种可为空性。前三个非常清楚,但我无法理解“未知”的含义。文档说它与泛型一起使用,但是当我尝试对泛型中T类型的无约束变量调用方法时,它只会发出警告,就好像该类型可以为空。我看不到unknown和nullable之间的区别。为什么未知存在?它如何表现出来?

Stu*_*art 11

采用以下通用方法:

public static T Get<T>(T value)
{
    return value;
}
Run Code Online (Sandbox Code Playgroud)

如果我们将其命名为Get<string>(s),则返回值是不可为null的;如果这样做Get<string?>(s),则它是可为null的。

但是,如果您使用诸如Get<T>(x)和的通用参数来调用它,并且T无法解析,例如,它是您的通用类的通用参数,如下所示...

class MyClass<T>
{
    void Method(T x)
    {
        var result = Get<T>(x);
        // is result nullable or non-nullable? It depends on T
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,编译器不知道最终是否会使用可为null或不可为null的类型调用它。

我们可以使用一个新的类型约束来表示T不能为空:

public static T Get<T>(T value) where T: notnull
{
    return value;
}
Run Code Online (Sandbox Code Playgroud)

但是,在T不受约束且仍处于开放状态的地方,可空性是未知的。

如果将这些未知数视为可为空,则可以编写以下代码:

class MyClass<T>
{
    void Method(T x)
    {
        var result = Get<T>(x);
        // reassign result to null, cause we we could if unknown was treated as nullable
        result = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

T不可为空的情况下,我们应该得到警告。因此,对于未知类型为null的可空性,我们在取消引用时需要警告,但也可能需要潜在的警告null