【发布时间】:2022-02-28 06:12:58
【问题描述】:
考虑这个最小的例子:
class A<T> where T : notnull
{
public T? Item; // OK!
public T? Something() => default; // OK!
public void Meow(ref T? thing1, out T? thing2) { thing2 = default; } // OK!
void Something(A<T>? other)
{
// OK!
Item = other is null ? default : other.Item;
// Error CS0403 : Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
Item = other is null ? null : other.Item;
// Error CS8978 : 'T' cannot be made nullable.
Item = other?.Item;
Item = other?.Item ?? default;
var x = other?.Item;
}
void Weird<U>(A<U>? other) where U : unmanaged
{
// OK!
var x = other?.Item;
}
void Weird2<U>(A<U>? other) where U : class
{
// OK!
var x = other?.Item;
}
void Weird3<U>(A<U>? other) where U : struct
{
// OK!
var x = other?.Item;
}
}
T 不为空
T? 要么是 T 要么是 null ...不是吗?在什么情况下这不是真的?
如果T是struct那么Item是Nullable<T>,可以由null分配
如果T 是class,那么“项目”就是T?,也可以由null 分配
我什至让T unmanaged 只是为了仔细检查(它应该是struct 的子集),并且可以由null 分配
...
那么存在什么类型的T 使得T? 不能保存值null?
...我也不太确定我问的问题是否正确...我真正的问题是“为什么它不起作用!!?!?!” :)
注意:此处已正确回答了类似问题:C#'s can't make `notnull` type nullable ... 但该答案适用于 C# 8 ... 从 C# 9 及更高版本开始,不再是这种情况
我还会在这里指出文档:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters ... 基本上说notnull 表示类/结构
...
编辑(事后考虑):如果是 IL 问题(IL 需要知道它是可空引用类型还是可空引用类型)...那么为什么 default 有效而 null 无效?显然 某些 版本的 IL 可以工作,所以这只是语言缺陷/怪癖?
【问题讨论】:
-
为什么你认为 C# 9.0 中有不同的规则?这些链接都没有提供证据
-
将您的 csproj 设置为 LangVersion 8.0 并尝试 Jon Skeet 的示例(来自第一个链接)。编译器会告诉你,除非你使用 9.0 或更高版本,否则它不会工作。
标签: c# generics non-nullable