我正在寻求有关属性初始值设定项、构造函数和对象初始值设定项如何为 C# 中的仅初始化属性工作的说明。我查阅了多种资源,包括书籍(C#10 in a Nutshell)、文档和 ChatGPT(这严重地自相矛盾并造成了进一步的歧义),但没有找到任何令人满意的答案。我的问题是:
如果我们为仅限 init 的属性编写属性初始值设定项,我们是否仍然可以使用构造函数和对象初始值设定项(以便属性初始值设定项写入的值先被构造函数覆盖,然后再被对象初始值设定项覆盖) ?
如果上述问题的答案是否定的,那么我们可以使用对象初始值设定项来覆盖构造函数设置的仅 init 属性的值吗?
public class Bunny
{
public string Name { get; init; }
// Can this be initialized like this: public string Name { get; init; } = "Cocoa";
// And if so, can this be overridden by a constructor or object initializer?
public Bunny(string name)
{
Name = name; // Can this constructor assignment be overridden by an object initializer?
}
}
var bunny1 = new Bunny("Fluffy"); // What is the value of Name here if a property initializer is used?
var bunny2 = new Bunny("Snowball") { Name = "Cinnabun" }; // What is the value of Name here? Is this allowed?
是否存在阻止以某些方式一起使用属性初始值设定项和构造函数或对象初始值设定项的约束或规则?如果是,它们是什么以及它们为何存在?
最后,这里的前提可能是错误的,但 ChatGPT 说你可以在同一个构造函数中多次修改仅 init 值的值;只有在退出构造函数后它才变得不可变。这是真的吗?如果是,为什么?
{
public string Name { get; init; }
public Bunny(string initialName)
{
// Initial assignment
Name = initialName;
Name = "IntermediateName"; // First modification
Name = "FinalName"; // Second modification
//Is this allowed? If yes, why? And if this is allowed, but overriding the value set by the property initializer isn't, why is that so?
}
}
我正在寻找这些行为及其背后原因的详细解释。我很欣赏任何可以澄清这些观点的见解或例子。
- 如果我们为仅限 init 的属性编写一个属性初始值设定项,我们可以吗 仍然使用构造函数和对象初始值设定项(因此 属性初始值设定项写入的值被覆盖 构造函数,然后是对象初始值设定项)?
是的。属性初始化程序代码正在初始化一个支持字段,该字段始终由编译器在实际代码之前注入到构造函数中。对象初始化程序在对象构造完成后开始工作。所以它是最后一个具有最高的“优先级”。
- 是否有限制或规则阻止属性初始值设定项和构造函数或对象初始值设定项一起使用 某些方式?如果是,它们是什么以及它们为何存在?
没有。
- 最后,这里的前提可能是错误的,但 ChatGPT 说您可以在同一时间内多次修改仅 init-only 值的值 构造函数;只有在退出构造函数后它才变得不可变。 这是真的吗?如果是,为什么?
不。例如,对象初始化程序在构造函数返回构造的对象之后工作。
深入研究此类问题的最佳方法是学习一点 IL 并广泛使用 ILSpy 或类似工具。