Init + private set accessors on the same 属性?

Init + private set accessors on the same property?

是否可以在同一个 属性 上使用 public 初始化访问器和私有 setter?

目前我收到错误 CS1007“属性 访问器已定义”。

public record Stuff
{
    public int MyProperty { get; init; private set; } // Error

    public void SetMyProperty(int value) => MyProperty = value;
}

var stuff = new Stuff
{
    MyProperty = 3, // Using the init accessor
};

stuff.SetMyProperty(4); // Using the private setter (indirectly)

我最好的猜测是使用一个私有成员变量,一个 属性 用于该变量,带有 getinit 访问器(不是自动实现的)和 setter成员函数。可以更简单地完成吗?

不,你不能。添加 init 关键字是为了使对象的属性不可变。

所以如果你有记录:

public record Stuff
{
    public int MyProperty { get; init; } // This can not be changed after initialization
}

MyProperty只能在你的记录初始化时设置。

如果您希望 属性 可变,那么您可以使用 set 访问器 代替 init

public record Stuff
{
    public int MyProperty { get; set; } // This can
}

正如@Jerry 的回答,您不能同时使用这两个设置器。这与 record/object.

的可变性有关

如果你想要 private seter 和一些初始化逻辑,我使用的方法是构造函数:

public record Stuff
{
    public Stuff(int myProperty)
    {
        MyProperty = myProperty;
    }

    public int MyProperty { get; private set; }

    public void SetMyProperty(int value) => MyProperty = value;
}

var stuff = new Stuff(3);
stuff.SetMyProperty(4);

都是关于域名要求的。

  • Stuff.MyProperty 是否需要公开修改?
  • 如果是,初始化 Stuff 实例时 属性 的默认值是多少?域是否需要默认值?

等..

类似于指定构造函数来初始化您的值,您可以使用私有支持字段,这样您仍然可以利用初始化逻辑并允许在没有特定构造函数的情况下进行初始化

public record Stuff
{
    private int _myProperty;

    public int MyProperty { get => _myProperty; init => _myProperty = value; }

    public void SetMyProperty(int value) => _myProperty = value;
}

var stuff = new Stuff
{
    MyProperty = 3 // Using the init accessor
};

stuff.SetMyProperty(4); // Using the private setter (indirectly)