例如,我有一个不可变类型
class Contact
{
// Read-only properties.
public string Name { get; }
public string Address { get; }
}
我希望我可以使用对象初始化器语法来创建一个Contact
Contact a = new Contact { Name = "John", Address = "23 Tennis RD" };
但我不能。在这种情况下,有什么可能利用强大的对象初始化器语法的方法吗?
最接近的是带有可选参数的构造函数:
class Contact
{
public string Name { get; }
public string Address { get; }
public Contact(string name = null, string address = null) {
Name = name;
Address = address;
}
}
然后你可以用参数名称来调用它:
new Contact(
name: "John",
address: "23 Tennis RD"
)
语法与对象初始值设定项略有不同,但它同样可读;和IMO,这种差异是一件好事,因为构造函数参数往往表示不可变的属性。您可以按任何顺序指定参数,也可以省略一些参数,因此它与对象初始值设定项语法一样强大。
这确实需要一些额外的代码(定义构造函数,分配所有属性),所以这比对象初始化器语法更麻烦。但也不太可怕,不可变对象的价值是值得的
(值得一提的是,C#7可能会得到语法简单得多的不可变的"记录类型"。这些类型可能会也可能不会进入最终版本,但听起来很酷。)
这已经过时了,但随着C#9的发布,您可以使用init
来实现所需的功能。
所以你的例子会变成:
class Contract
{
// Read-only properties.
public string Name { get; init; }
public string Address { get; init; }
}
然后你可以初始化:
// success!
Contract a = new Contract { Name = "John", Address = "23 Tennis RD" };
但在设置参数后,您仍然无法修改这些参数(因此它们仍然是只读的)。
// error!
a.Name = "Uncle Bob";
在后台,当您使用C#9之前的对象初始值设定项语法时,编译器将首先调用默认构造函数,然后设置您指定的属性值。显然,如果这些属性是只读的(即只有get
方法),它就不能设置它们。仅限init
的setter只允许在初始化时通过构造函数方法或对象初始化器语法设置值。
更多信息请点击此处:https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#init-仅设置
不可以,您不能将它与只读属性一起使用
以下是comparism中不同的属性和字段类型。
public class sometype {
public int readonlyProp{
get;
}
public int normalProp {
get;
set;
}
public const int constField = 3;
public readonly int readonlyField = 3;
public int normalField = 3;
public void test() {
sometype test = new sometype() { readonlyProp = 3}; // Doesn't work -> Property or indexer is readonly
sometype test1 = new sometype() { normalProp = 3 }; // ok
sometype test2 = new sometype() { constField = 3 }; // Doesn't work -> Static field or property
sometype test3 = new sometype() { readonlyField = 3 }; // Doesn't work -> readonly field
sometype test4 = new sometype() { normalField = 3 }; // ok
}
}
重要的是要理解const字段被认为是静态的,因此不是实例成员。由于对象初始值设定项用于实例成员,所以这不起作用。
对象初始化器将首先构造对象,然后设置属性值。它需要二传手。
这是的缩写
Contact a = new Contact();
a.Name = "John";
a.Address = "23 Tennis RD";
一旦构造了对象,就不能设置只读字段的值。要使该类不可变,您需要创建一个构造函数来获取这些值:
class Contact // Immutable class
{
// Read-only properties.
public string Name { get; }
public string Address { get; }
public Contact(string name, string address)
{
this.Name = name;
this.Address = address;
}
}