当在 C# 8.0 中启用 NRT(Nullable Reference Types)时,代码中的 null 引用检查会得到加强,以帮助开发人员更好地识别和处理可能的空引用异常。在这种情况下,使用 T? 表示可空类型,其中 T 可以是引用类型或值类型。但是,如果使用 where T : struct 限定类型参数 T 为值类型,则 T? 表示 Nullable<T>

var a = GetA<int>();
var b = GetB<int>();

T? GetA<T>()
{
    return default;
}

T? GetB<T>() where T:struct
{
    return default;
}

在上述代码中,GetA<T>() 方法返回类型为 T?,因为 T 没有被限定为值类型,所以 T? 表示可空类型 T。由于 int 是值类型,因此 GetA<int>() 返回 0,而不是 null

相反,GetB<T>() 方法限定类型参数 T 为值类型,因此 T? 表示 Nullable<T>。由于 int 是值类型,因此 GetB<int>() 返回 null,而不是 0

在使用 NRT 时,开发人员应该注意类型参数的限制以及 null 引用的处理,以确保代码的正确性和可靠性。同时,建议开发人员在代码中使用尽可能多的 null 引用检查和空引用异常处理,以避免潜在的编程错误。