省略了setter的属性和私有setter的属性之间有什么区别?
public string Foo { get; private set; }
对比
public string Foo { get; }
省略了setter的属性和私有setter的属性之间有什么区别?
public string Foo { get; private set; }
对比
public string Foo { get; }
C# 6 中,只有 getter 的属性仅可以从构造函数中进行设置,在其它任何地方都只能用于读取。
一个带有 private set;
的属性则可以在该类的任何位置进行设置。
readonly
关键字实现此目的:private readonly string _name;
是 public string Name { get; }
的私有类比。 (顺便说一下:public readonly Name { get; }
是冗余的,甚至编译器也不允许这样做。) - JohnB如果您在类之外使用此语法,它不会改变任何内容:
public string Foo { get; }
但是您将无法在类内更新Foo
,除非在构造函数中这么做,为此,您需要使用私有设置器:
public string Foo { get; private set; }
不同之处在于,生成的代码将在第二种情况下产生一个只读字段,并且该属性显然不会有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方法也已经被移除。
因此,这实际上是创建具有真正只读属性的简单类型的最佳方式。不仅属性本身不可写入,而且后备字段也是只读的,这意味着您现在更适合轻松编写不可变类型。
static
没有影响。 - Lasse V. Karlsenprivate
的setter方法是一个只能从类内部调用的私有设置方法。
omitted
的setter方法使属性变为只读。因此,您只能在构造函数或通过静态初始化来设置该属性的值。
如果一个属性省略了setter方法,在类构造函数内和类外其他地方都是只读的。
如果一个属性设置了私有的setter方法,那么在类外部(包括子类)是只读的,但在内部是可以被写入的。