同一属性上的 Init + 私有集访问器?

问题描述 投票:0回答:4

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

目前我收到错误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)

我最好的猜测是使用私有成员变量,该变量的属性带有

get
init
访问器(不是自动实现的)和 setter 成员函数。可以更轻松地完成吗?

c# c#-9.0
4个回答
37
投票

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

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)

7
投票

不,你不能。添加 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
}

2
投票

作为@Jerry的答案,你不能同时使用这两个设置器。这与记录/对象的可变性有关。

如果你想要

private set
和一些初始化逻辑,我使用的方式是构造函数:

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 实例初始化时,该属性的默认值是什么?域是否需要默认值?

等等..


0
投票

如果您有一条包含多个属性的记录,并且希望仅更改其中几个属性的设置器的可访问性,您可以使用以下语法:

public sealed record Stuff(int MyProperty, string ImutableProperty, DateTimeOffset AnotherProperty)
{
    public int MyProperty { get; private set; } = MyProperty;   
    public DateTimeOffset AnotherProperty { get; set; } = AnotherProperty;
        
    public void SetMyProperty(int value) => MyProperty = value;
}

在此代码中,

MyProperty
有一个私有setter,因此只能在类构造函数中设置。
AnotherProperty
有一个公共设置器,允许从外部代码设置它。此外,构造函数用于在创建记录实例时设置属性的初始值。

© www.soinside.com 2019 - 2024. All rights reserved.