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

Posted

技术标签:

【中文标题】什么是 C# 8 中的未知可空性?【英文标题】:What is Unknown Nullability in C# 8? 【发布时间】:2020-03-20 05:53:51 【问题描述】:

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

【问题讨论】:

【参考方案1】:

采取以下通用方法:

public static T Get<T>(T value)

    return value;

如果我们称它为Get&lt;string&gt;(s),则返回不可为空,如果我们称其为Get&lt;string?&gt;(s),则返回可空。

但是,如果您使用诸如 Get&lt;T&gt;(x)T 之类的通用参数调用它,则无法解析,例如,它是您的通用类的通用参数,如下所示...

class MyClass<T>

    void Method(T x)
    
        var result = Get<T>(x);
        // is result nullable or non-nullable? It depends on T
    

这里编译器不知道最终是否会使用可空类型或不可空类型调用它。

我们可以使用一个新的类型约束来表示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(x);结果.ToString();编译器抱怨取消引用可能为 null 的值。在这种情况下,我看不出未知与简单可为空有什么不同。 就警告而言,它们的行为相同,但语义不同。您可以说差异是学术上的,如果这是您的观点,那么我同意。 我仍然想知道为什么要引入差异。出于学术目的在语言中引入这种区别似乎很奇怪。 我的错,只是重新阅读规范,更新答案,最后一部分解释它。 啊这更像

以上是关于什么是 C# 8 中的未知可空性?的主要内容,如果未能解决你的问题,请参考以下文章

可空引用类型 - 通过接受的参数返回类型可空性

Firebase,Swift:返回类型上的可空性说明符冲突,“可空”与现有说明符“非空”冲突

Kotlin空安全 ① ( Kotlin 的空安全机制 | 变量可空性 | 默认变量不可赋空值 | 声明可空类型变量 )

C# 8中的可空引用类型

Pyspark 模式:如何检查可空性?

[译] Dart中可空性语法的定案: a?[b] 或 a?.[b]