我想知道为什么不可能做到以下几点:
struct TestStruct
{
public readonly object TestField;
}
TestStruct ts = new TestStruct {
/* TestField = "something" // Impossible */
};
Run Code Online (Sandbox Code Playgroud)
对象初始值设定项是否应该能够设置字段的值?
Xeu*_*ron 14
C# 9 Init-Only Properties(尽管名称如此)将允许初始化语法也能够设置只读字段。
\n以下是从链接复制的相关部分。
\n\n这是对象初始值设定项的一个简单示例。
\nnew Person\n{\n FirstName = "Scott",\n LastName = "Hunter"\n}\n
Run Code Online (Sandbox Code Playgroud)\n今天的一大限制是属性必须是可变的,对象初始值设定项才能工作:它们的功能是首先调用 object\xe2\x80\x99s 构造函数(在本例中是默认的无参数构造函数),然后分配给属性设置器。
\n仅初始化属性可以解决这个问题!他们引入了一个init
访问器,它是访问器的变体set
,只能在对象初始化期间调用:
public class Person\n{\n public string FirstName { get; init; }\n public string LastName { get; init; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n通过此声明,上面的客户端代码仍然合法,但任何后续对FirstName
和LastName
属性的赋值都是错误的。
因为init
访问器只能在初始化期间调用,所以它们可以改变readonly
封闭类的字段,就像在构造函数中一样。
public class Person\n{\n private readonly string firstName;\n private readonly string lastName;\n \n public string FirstName \n { \n get => firstName; \n init => firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));\n }\n public string LastName \n { \n get => lastName; \n init => lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
Mic*_*Liu 10
readonly
表示该字段只能在构造函数(或字段初始值设定项)中设置.在构造函数返回后设置对象初始值设定项中指定的属性.那是,
TestStruct ts = new TestStruct {
TestField = "something"
};
Run Code Online (Sandbox Code Playgroud)
基本上相当于
TestStruct ts = new TestStruct();
ts.TestField = "something";
Run Code Online (Sandbox Code Playgroud)
(在Debug构建中,编译器可能会使用临时变量,但您可以理解.)
对象初始化程序在内部使用临时对象,然后将每个值分配给属性.拥有一个只读字段会破坏它.
以下
TestStruct ts = new TestStruct
{
TestField = "something";
};
Run Code Online (Sandbox Code Playgroud)
会翻译成
TestStruct ts;
var tmp = new TestStruct();
tmp.TestField = "something"; //this is not possible
ts = tmp;
Run Code Online (Sandbox Code Playgroud)
(这是Jon Skeet解释临时对象与对象初始化器的用法的答案,但有不同的情况)