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


12

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

Answers:


12

采用以下通用方法:

public static T Get<T>(T value)
{
    return value;
}

如果我们将其命名为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
    }
}

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

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

public static T Get<T>(T value) where T: notnull
{
    return value;
}

但是,在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;
    }
}

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


当我做var result = Test.Get <T>(x); result.ToString(); 编译器抱怨取消引用可能为null的值。在这种情况下,我不知道未知与单纯可为空有何不同。
斯蒂尔加

1
就警告而言,它们的行为相同,但在语义上有所不同。您可以说差异是学术上的,如果那是您的观点,那么我同意。
Stuart

1
我仍然想知道为什么引入了差异。出于学术目的在语言中引入这种区别似乎很奇怪。
斯蒂尔加

我的不好,只是重新阅读规范,更新答案,最后一部分对此进行了解释。
Stuart

1
啊,这更像是
Stilgar
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.