[英]C# 9 Nullable types issues
考虑以下(VS 16.8.0 Preview 2.1 C# 9.0 preview)代码:
#nullable enable
using System.Collections.Generic;
class Archive<T> where T : notnull
{
readonly Dictionary<string, T> Dict = new();
public T? GetAt(string key)
{
return Dict.TryGetValue(key, out var value) ? value : default;
}
}
class Manager
{
public int Age { get; set; }
}
class Main34
{
long F3()
{
Archive<long> a = new();
var johnAge = a.GetAt("john");
if (johnAge is null) return -1; // Error CS0037 Cannot convert null to 'long' because it is a non - nullable value type
return johnAge;
}
long F4()
{
Archive<Manager> a = new();
var johnAge = a.GetAt("john");
//if (johnAge is null) return -1;
return johnAge.Age; // Correct ! warning "Derefrencing of a possibly null reference" will be removed if line above unremarked
}
}
我很难理解/解决 F3 中的错误,似乎编译器认为 johnAge 存在long
long?
(正如我通过在 VS 中悬停在它上面来验证的那样)尽管Archive<T>.GetAt
的返回是T?
有没有办法让通用存档可以做我想做的事情(即使 T 是不可为空的基本类型,即 long,也返回 Nullable 的 GetAt 方法)?
从根本上说,这归结为可空值类型和可空引用类型非常非常不同。 CLR 知道可空值类型,但就 CLR 而言,可空引用类型只是“普通的引用类型,有一个属性告诉编译器是否应将其视为可为空的”。
当T
具有notnull
约束时,类型T?
只在 IL 中编译为T
它必须 - 它不能编译为Nullable<T>
,因为Nullable<T>
将T
约束为值类型。
因此,对于Archive<long>
,如果在字典中找不到键,则GetAt
方法将返回 0L - 它不会(也不能)返回Nullable<long>
的空值,这就是您的F3
代码有效地期待。
整个“可空引用类型”功能的缺点是试图在基本上没有它的类型系统上添加可空感知的“贴面”。 我敢肯定,如果现在从头开始设计新的运行时和语言,它会尝试更紧密地统一这一点。 事实上,我相信这个特性仍然有很多价值——但是当涉及到泛型时,它肯定会让事情变得非常棘手。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.