【发布时间】:2020-11-20 14:54:26
【问题描述】:
我正在使用 NET 5.0 测试 c# 9.0,但有些东西我不明白。我启用了<nullable>enable</nullable>。
如果我写一个类
public class Potato {
public string Colour { get; set; }
public string Flavour { get; set; }
}
我收到警告 CS8618: Non-nullable propery 'Colour' must contain a non-null value when existing constructor. Consider declaring the propery as nullable. 我不想声明它可以为空,这就是我启用标签的原因...
然后,我声明构造函数:
public class Potato
{
public Potato(string colour, string flavour)
{
this.Colour = colour;
this.Flavour = flavour;
}
public string Colour { get; set; }
public string Flavour { get; set; }
}
到目前为止一切顺利。现在我想使用对象初始化器创建一个Potato 对象:
var sweetPotato = new Potato {
Colour = "orange",
Flavour = "tasty",
};
现在我收到了CS7036: There is no argument given that corresponds to the required formal parameter 'colour' of 'Potato.Potato(string, object) 的投诉。因此,它尝试使用我明确声明但我没有引入参数的构造函数。我应该这样做:
var sweetPotato = new Potato(
colour: "orange",
flavour: "tasty");
但是这里我没有使用对象初始化器。
另一种选择是将类声明为
public class Potato
{
public string Colour { get; set; } = null!;
public string Flavour { get; set; } = null!;
}
使用 null! 元素,但这允许一些奇怪的事情,例如:
var sweetPotato = new Potato()
{
Colour = "orange",
};
我认为这非常奇怪。我声明了 2 个不可为空的属性,并且感谢 null! 我可以使用一个属性加载对象,但不能加载第二个属性。这打破了我的可空标签!
那么我的问题是:如果启用了可空标记,是否可以使用具有不可空属性的对象初始化器?
如果不是,我认为对于具有不可为空属性的类,不涉及任何null!,默认构造函数不应该是空的,而是具有所有参数的,并且应该可以初始化具有对象初始化程序形式的对象,只要所有不可为空的属性都已初始化。
【问题讨论】:
-
您所做的是使所有内容都非可空,除非使用
?明确标记为可空。如果您想要旧的行为,请删除nullable设置。 -
至于剩下的问题,大部分都是尝试使用无效的语法——如果你指定了一个构造函数,你必须使用它并提供所有参数。这不受
nullable标签的影响。您可以对所有类使用对象初始化器语法。但是,如果该类没有默认构造函数,则您必须使用其中一个构造函数 -
顺便说一句,您尝试的代码看起来很像
record。除了将匿名类型存储为不透明的object的相当奇怪的尝试之外,以后没有人可以使用它。您不能使用.Flavour.Tasty,因为object没有Tasty属性。您也不能将其转换为特定类型,因为它包含匿名类型。您应该将Potato设为泛型类或将dynamic用于Flavour -
感谢您的回答@PanagiotisKanavos。 1)当我的意思是“我不想宣布它可以为空”时,我写了“不可为空”。我修好了它。对困惑感到抱歉。 2)对象事物是不相关的。我用一个字符串改变了它。 3) 记录可以是可变的,但它们主要是为了更好地支持不可变数据模型而构建的。就我而言,我需要更改属性。 4)我的问题的核心仍然不清楚:如何在具有不可为空元素的类上使用对象初始化器语法?如果我不指定构造函数,我会得到 CS8614,如果我指定它,我必须使用它...
-
简短回答是否定的,该语言不支持所需的初始化属性。您可能希望密切关注此提案:github.com/dotnet/csharplang/issues/3630