省略的 setter 与私有的 setter?

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

省略 setter 的属性和带有私有 setter 的属性有什么区别?

public string Foo { get; private set; }

public string Foo { get; }
c# c#-6.0
6个回答
79
投票

在 C# 6 中,

get;
只有属性只能从构造函数中设置。从其他地方来看,它是只读的。

带有

private set;
的属性可以从该类内的任何位置进行设置。


12
投票

从类外部来看,如果使用以下语法,它不会改变任何内容:

public string Foo { get; }

但是你将无法在类中更新

Foo
,除了在构造函数中,为此,你需要私有设置器:

public string Foo { get; private set; }

10
投票

不同之处在于,在第二种情况下,生成的代码将生成一个只读字段,并且显然该属性不会有 setter。

我们来做一个真实的例子:

public class Test
{
    public Test(string name) { Name = name; }
    public string Name { get; private set; }
}

编译器会这样编译:

public class Test
{
    private string <Name>k__BackingField;
    public Test(string name)
    {
        <Name>k__BackingField = name;
    }
    public string Name
    {
        get { return <Name>k__BackingField; }
        private set { <Name>k__BackingField = value; }
    }
}

如您所见,编译器已自动重写您的代码以拥有该属性的支持字段。字段名称将是那个神秘的名称,它是合法的 .NET,但不是 C#,这意味着您永远不能编写与此类自动生成的成员冲突的 C# 代码。

基本上,C# 中的自动属性只是带有支持字段的属性的语法糖,正在编译的实际属性仍然有一个支持字段,你只是不必显式地编写它。

如您所见,它还自动重写了构造函数以直接写入字段。请注意,这将在写入属性的类中的任何地方完成,因为无论如何都不可能有任何自定义代码介于两者之间。

现在让我们从属性中删除 setter 并看看会发生什么:

public class Test
{
    private readonly string <Name>k__BackingField;
    public Test(string name)
    {
        <Name>k__BackingField = name;
    }
    public string Name
    {
        get { return <Name>k__BackingField; }
    }
}

请注意,该字段现在是只读的,并且显然 setter 也已从该属性中消失。

因此,这实际上是现在创建具有 true 只读属性的简单类型的最佳方法,不仅属性本身不可写,而且支持字段也是只读的,这意味着您现在可以更好地轻松编写不可变类型 .


5
投票

private
setter 是一种私有 set 方法,您只能在班级内部使用。

omissed 设置器使属性

readonly
。因此,您只能在构造函数中或通过静态初始化来设置此属性的值。


4
投票

省略 setter 的属性在除类构造函数之外的所有位置都是只读的 - 包括在类内部。

具有私有 setter 的属性只能在外部读取(甚至对于子类),但在内部可写。


0
投票

省略虚拟基类属性上的 setter 很有用,您希望派生子类重写这些属性,以便基类方法使用重写的properties 属性。该方法遵循 SOLID 中的开/闭原则。

public class BaseClass
{
    public virtual int CookiesToEat { get; }
    
    public void EatCookies()
    {
        Console.WriteLine($"Eating {CookiesToEat}");
    }    
}

public class ChildClass : BaseClass
{
    get { return 5; }
}

BaseClass bc = new ChildClass();
bc.EatCookies(); 
© www.soinside.com 2019 - 2024. All rights reserved.