我一直在阅读 C#9 中的 init-only 属性,但我认为我们已经有了只能在构造函数中设置的只读属性。在那之后,它是不可变的。
例如,在这里的类中,Name和Description都可以在构造函数中赋值,但只能在构造函数中赋值,这正是 init-only 属性的描述方式。
class Thingy {
public Thingy(string name, string description){
Name = name;
Description = description;
}
public string Name { get; }
public string Description { get; }
public override string ToString()
=> $"{Name}: {Description}";
}
Run Code Online (Sandbox Code Playgroud)
using System;
class Program {
public static void Main (string[] args) {
var thingy = new Thingy("Test", "This is a test object");
Console.WriteLine(thingy);
// thingy.Name = “Illegal”; <— Won’t compile this …Run Code Online (Sandbox Code Playgroud) C# 9.0 引入了仅 init 类属性功能,但在使用 Activator.CreateInstance 按类类型创建实例时无法使用它们。一个简单的例子:
class Person
{
public string Name { get; init; }
}
void Test()
{
Person person = (Person)Activator.CreateInstance(typeof(Person));
person.Name = "Bob"; // Doesn't work
}
Run Code Online (Sandbox Code Playgroud)
寻找除使用构造函数参数(太多)之外的解决方案。
我尝试编写一些 C# 代码来创建一个 init-only 属性。我惊讶地发现该属性可以在运行时更改。我是否误解了不变性的概念?我正在使用 Visual Studio 社区 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; }
}
}
Run Code Online (Sandbox Code Playgroud)
运行时示例。
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> …Run Code Online (Sandbox Code Playgroud)