省略 setter 与私有 setter?

Omitted setter vs private setter?

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

public string Foo { get; private set; }

public string Foo { get; }

在 class 之外,如果您使用此语法,它不会改变任何内容:

public string Foo { get; }

但是您将无法在 class 中更新 Foo,除了在构造函数中,要这样做,您需要私有 setter:

public string Foo { get; private set; }

在 C# 6 中,get; 只有属性只能从构造函数中设置。在其他任何地方,它都是只读的。

带有 private set; 的 属性 可以从 class.

中的任何地方设置

省略了 setter 的 属性 在除 class 构造函数之外的任何地方都是只读的 - 包括 class.

内部

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

private setter 是 - 嗯 - 一种私有设置方法,您只能在 class 内部使用。

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

区别在于生成的代码在第二种情况下会产生一个只读字段,显然 属性 不会有 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# 中的自动属性只是带有支持字段的 属性 的语法糖,实际编译的 属性 仍然有一个支持字段,您只是不必编写它明确。

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

现在让我们从 属性 中删除 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 只读属性的简单类型的最佳方法,不仅 属性 本身不可写,而且支持字段是也是只读的,这意味着您现在可以更好地轻松编写 不可变类型 .