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

Fre*_*red 38 c# c#-6.0

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

public string Foo { get; private set; }
Run Code Online (Sandbox Code Playgroud)

VS

public string Foo { get; }
Run Code Online (Sandbox Code Playgroud)

Pat*_*man 51

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

private set;可以在该类中的任何位置设置具有a的属性.


Tho*_*oub 10

从类外部,如果使用此语法,它将不会更改任何内容:

public string Foo { get; }
Run Code Online (Sandbox Code Playgroud)

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

public string Foo { get; private set; }
Run Code Online (Sandbox Code Playgroud)


ang*_*son 6

区别在于生成的代码将在第二种情况下产生只读字段,显然该属性将没有setter.

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

public class Test
{
    public Test(string name) { Name = name; }
    public string Name { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

编译器将像这样编译:

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,编译器已自动重写您的代码,以便为该属性提供支持字段.字段名称将是隐藏的名称,这是合法的.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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Ren*_*ogt 5

setterprivate是一种私有 set 方法,您只能在类内部使用。

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