在同一属性上使用Init和私有set访问器?

25

能否在同一属性上使用公共的初始化访问器和私有的设置器?

目前我遇到了错误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也是一个setter。 - Panagiotis Kanavos
2
不可能的,init 访问器使用与 set 访问器相同的 set_MyProperty 设置方法:只是用 modreq 进行了修饰。 - canton7
9
init 的整个概念是使属性不可变。拥有一个 setter 方法会破坏这个目的。 - Jerry
3
目标是拥有“大部分不可变”对象,其中的原则是不可变性,但有一些明确定义的例外。我们可以使用 with,但这并不能使任何逻辑(例如一致性检查)成为可能。 - Gábor Imre
1
我想我能为此提出的最佳解决方案是使用私有设置器,并通过构造函数设置初始值。 - Jerry
3个回答

36
与指定构造函数以初始化值类似,您可以使用私有后备字段,以便仍然利用初始化逻辑并允许没有特定构造函数的初始化。
类似于指定构造函数以初始化值,您可以使用私有后备字段,以便仍然利用初始化逻辑并允许无需特定构造函数进行初始化。
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)

6

不行。在对象上添加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
}

1
谢谢Hasan,我确实是指“设置”。 - Jerry

2

正如@Jerry的回答,你不能同时使用两个setter。这与记录/对象的可变性有关。

如果您想要私有设置器和一些初始化逻辑,我使用的方法是构造函数:

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实例时,该属性的默认值是什么?领域是否期望有一个默认值?

等等...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接