省略的二传手与私人二传手?

时间:2016-04-22 11:16:54

标签: c# c#-6.0

具有省略的setter的属性与具有私有setter的属性之间有什么区别?

public string Foo { get; private set; }

VS

public string Foo { get; }

5 个答案:

答案 0 :(得分:42)

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

可以从该类中的任何位置设置具有private set;的属性。

答案 1 :(得分:10)

如果你使用这种语法,从课堂外面来看,它不会改变任何东西:

public string Foo { get; }

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

public string Foo { get; private set; }

答案 2 :(得分:6)

不同之处在于,生成的代码将在第二种情况下生成只读字段,显然该属性不会有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; }
    }
}

请注意,该字段现在只是readonly,而且很明显,setter也已经离开了该属性。

所以这实际上是现在用 true readonly属性创建简单类型的最好方法,不仅属性本身不可写,而且后备字段也是readonly意味着你现在装备更好轻松编写不可变类型

答案 3 :(得分:4)

private setter是 - 嗯 - 您可以在课堂内使用的私人套装方法。

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

答案 4 :(得分:3)

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

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