1

我正在使用 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!涉及任何内容,默认构造函数不应该是空的,而是具有所有参数的,并且应该可以使用对象初始化器来初始化对象形式,只要所有不可为空的属性都已初始化。

4

2 回答 2

1

的默认值为string空。由于您的属性声明未定义默认值,因此它们将默认为default,这恰好nullstring. 问题是您没有将类型声明为nullable.

解决方案是分配一个默认值,例如String.Empty

public class Potato
{
    public string Colour { get; set; } = String.Empty;

    public string Flavour { get; set; } = String.Empty;
}
于 2020-12-04T22:25:34.647 回答
1

我知道这是一个老问题,但这里是全面的答案:

  1. 通过添加<nullable>true<nullable>您制作的标签,以便所有可空值都必须用?
  2. 因为 1.,并且由于您没有添加?到他们的类型中,因此ColourFlavour不能NULL
  3. 由于 2.,您必须提供一个构造函数来初始化两者的值Colour-Flavour默认的无参数构造函数将不起作用,因为它本身什么也不做,并且会返回一个NULL同时包含Colourand的对象Flavour,因为这是它们类型的默认值,您要求编译器不允许

下面的片段:

var sweetPotato = new Potato { 
    Colour = "orange",
    Flavour = "tasty",
};

使用默认的无参数构造函数,因此不能使用。它的简写等同于:

var sweetPotato = new Potato(); // sweetPotato has Colour and Flavour NULL
sweetPotato.Colour = "orange";  // sweetPotato still has Flavour NULL
sweetPotato.Flavour = "tasty";

如您所见,它将首先创建对象(使用默认值)并稍后分配值。但是由于您不允许 的默认值NULL,它会失败

这就是为什么如果你不允许它们为空,你必须添加一个初始化它们的构造函数,并且你必须使用那个构造函数

如果它们的类型是具有不同默认值的原语(例如 anint或 a ),则这不适用double。在这种情况下,默认的无参数构造函数将起作用。但是通过使用默认值为 , 的类型NULL(类似string或任何object派生类型),您可以通过添加使它们为空,?或者您必须使用构造函数将它们初始化为NULL.

于 2021-05-19T15:44:02.863 回答