C# 省略的setter与私有setter?

C# 省略的setter与私有setter?,c#,c#-6.0,C#,C# 6.0,具有省略的setter的属性和具有私有setter的属性之间有什么区别 public string Foo { get; private set; } vs 从类外,如果使用以下语法,则不会更改任何内容: public string Foo { get; } 但是您将无法在类中更新Foo,除非在构造函数中,为此,您将需要私有setter: public string Foo { get; private set; } 在C#6中,get仅属性只能从构造函数设置。从其他地方看,它是只读的 具

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

public string Foo { get; private set; }
vs


从类外,如果使用以下语法,则不会更改任何内容:

public string Foo { get; }
但是您将无法在类中更新
Foo
,除非在构造函数中,为此,您将需要私有setter:

public string Foo { get; private set; }
在C#6中,
get仅属性只能从构造函数设置。从其他地方看,它是只读的


具有
私有集的属性可以从该类中的任何位置进行设置。

省略setter的属性在除类构造函数之外的任何位置都是只读的,包括类内部


带有私有setter的属性在外部是只读的(甚至对子类也是如此),但在内部是可写的。

私有的
setter是一个私有的set方法,您只能从类内部使用


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

不同之处在于,生成的代码将在第二种情况下生成一个只读字段,并且该属性显然没有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; }
    }
}
公共类测试
{
私有字符串k__BackingField;
公共测试(字符串名称)
{
k_uubackingfield=名称;
}
公共字符串名
{
获取{return k_ubackingfield;}
私有集{k_uubackingfield=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; }
    }
}
公共类测试
{
私有只读字符串k__BackingField;
公共测试(字符串名称)
{
k_uubackingfield=名称;
}
公共字符串名
{
获取{return k_ubackingfield;}
}
}
请注意,该字段现在是只读的,显然setter也已从属性中删除


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

simple:省略setter的属性没有setter。您不能在属性声明或构造函数之外重新分配属性。重复警报:,@tuChargupta此属性被标记为C#-6.0所选的重复实际上说明了新语法的预期目标,尽管它同时包含旧文本和新的C#-6后文本,但它仍然回答了这个问题,真正的不变性和只读支持字段。有趣的是,我想这也适用于静态只读属性(即,当它仅声明自动getter时)是的,
static
在这方面并不重要。我没有尝试查看这种情况下发生了什么(实例或只有
get;
的私有属性)。因此,我不会手动声明更多的
readonly
字段;P(除非我需要不封装它们,但是在没有封装的情况下访问类字段仍然是一种糟糕的编码实践)。您只能在构造函数中设置它。@帕特里克霍夫曼谢谢您的评论,我以前不知道!有趣的是,每个答案的这一部分都错了,而且仍然获得了选票,而我的答案从一开始就指出了这一点,但没有获得任何选票…@Patrickhoffman Upvows常常忘恩负义,有些选民在投票前甚至没有花时间阅读全部答案。我似乎无法将该属性声明为
只读
。编译器抱怨“修饰符'readonly'对此项无效”。我明白了。我想知道为什么存在省略setter的功能。声明只可由构造函数设置,但可由类内方法设置的属性的原因是什么?为了防止从该方法内的某个位置错误地设置该属性,可以在类中的其他位置更新该属性,但不能重新分配它。例如,如果属性是一个列表,即使没有声明setter,您也可以在类中的任何位置调用Clear()和Add()。@Fred因为有时您不希望在构造函数中初始设置属性引用后更改它。您可以使用私有数据成员以及
readonly
关键字:
private readonly string\u name
是对
公共字符串名{get;}
的私有模拟。(顺便说一句:
public readonly Name{get;}
是冗余的,编译器甚至不允许使用。)
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; }
    }
}