【发布时间】:2019-12-06 14:43:31
【问题描述】:
在 C#8.0 中使用可为空的引用类型,给出这个简化的代码,其中 T 可以是任何值类型或引用类型,并且空值是引用类型 T 实例的有效值:
public class C<T>
{
public T P { get; set; }
}
编译器发出警告CS8618 "Non-nullable property 'P' is uninitialized. Consider declaring the property as nullable."。
我怎样才能满足编译器并消除此警告(不抑制 CS8618)?
是否有我可以应用的属性或类型参数约束?那怎么办?
我想出的最好的是
public T P { get; set; } = default!;
但我希望有一种方法可以在不使用 null-forgiving/"dammit" 运算符 ('!') 的情况下做到这一点。
注意:您不能将属性类型声明为T? - CS8627。此外,这意味着返回的任何值类型都是Nullable<T>,这不是预期的。 (Read more about this e.g. here.)
编辑:我注意到这也有效:
public class C<T>
{
public C()
{
P = default;
}
[AllowNull]
public T P { get; set; }
}
但是我更喜欢使用自动属性初始化器。
【问题讨论】:
-
首先你需要决定你想要做什么。在第一次设置之前,you 希望该值包含什么?一些默认实例?它应该是只读的吗?
get;是否有可能返回null?也许您应该使用Option风格的类型,它可以有一个值或者是None? -
每个选项都可以以不同的方式实现,通过构造函数、可空性属性或自定义选项结构like this one
-
我希望属性值是默认值。 IE。对于
int,它应该是'0',对于object,它应该是'null',就好像这个类是用这些类型中的任何一个而不是泛型类型参数定义的一样。 -
那是什么
default?它不能为 null 并且仍然是不可为 null 的引用。这就是该功能的全部意义所在。如果您希望它为空,请将其设置为T?。如果您真的想利用不可为空的类型,请修改您的设计,使其不需要需要空值 -
我建议使用
class约束。泛型类型很少需要同时支持类和结构。由于可空性对它们中的每一个都有不同的作用,因此您会立即遇到此问题。否则,也许可以尝试使用[AllowNull]和default!。
标签: c# generics nullable c#-8.0 nullable-reference-types