如何解决是否可以在运行时设置 C# init-only 属性?
我尝试编写一些 C# 代码来创建仅用于初始化的属性。 我惊讶地发现该属性可以在运行时更改。 我是否误解了不变性的概念? 我使用的是 Visual Studio Community 16.9.3。
示例代码。
namespace TonyStachnicki.Windows {
using System.Management.Automation;
[Cmdlet(VerbsCommon.New,"Person")]
public class NewPerson : Cmdlet {
protected override void ProcessRecord() {
var _Person = new Person {
Name = "Jane Dough"
};
WriteObject(_Person);
}
}
public class Person {
public string Name { get; init; }
}
}
运行时示例。
PS D:\Users\Tony> ($Person = New-Person)
Name
----
Jane Dough
PS D:\Users\Tony> $Person.Name = "John Smith"
PS D:\Users\Tony> $Person
Name
----
John Smith
PS D:\Users\Tony> $Person.Name = "Jane Jones"
PS D:\Users\Tony> $Person
Name
----
Jane Jones
PS D:\Users\Tony>
程序与这个 Person 类的行为相同。
public class Person {
public string Name {
get { return m_Name; }
init { m_Name = value; }
}
private readonly string m_Name;
}
在这种情况下,只读修饰符也被忽略。
我想大多数人都会对 init-only 特性的效果感到惊讶。
解决方法
您的 C# 代码不会重新分配值,因此这里没有违反 C# 规则。 powershell 是否取消规则完全取决于 powershell。注意:
- 反射 API 故意不阻止访问 - 这是为了使序列化程序、ORM 等无需更改即可正常工作(并且反射 API 不需要更改,这意味着它在较旧的运行时继续保持相同的工作方式)
- 更一般的 IL 访问检查取决于“modreq”——但这取决于相关的 IL 工具(通常是语言编译器)来做出决定;如果特定工具忽略“modreq”,则:它忽略它
来自 this source :“当使用 init 关键字时,它将属性限制为只能由构造函数设置或在嵌套对象创建期间设置。”这意味着
factor()
是合法的(因为它使用嵌套对象创建)。这与 C# 9.0 之前的情况不同,在 C# 9.0 之前的情况下,您可以在没有 setter 的情况下定义属性。这允许在构造函数中只初始化,而不允许在嵌套对象创建中进行初始化。
因此,如果您将 var _Person = new Person {
Name = "Jane Dough"
};
类定义为:
Person
您的代码将无法编译(并且您需要为 Person 类提供一个非默认构造函数以将 Name 设置为某物)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。