C#中的私人“设置” – 无法将我的大脑包裹起来

我已经看到很多使用类似的东西编写的示例代码(请原谅这是多么可怕的jar头):

public class Test { public object Thingy { get; private set; } } 

不幸的是,这些例子从未真正解释为什么’set’被设置为私有。 所以,我只是想知道是否有一个好的,常见的例子可以向我说明为什么会使用这样的东西。

我有点看到它 – 除了设置该字段外,还可以运行属性来处理一些额外的逻辑。 我只是对如何调用它感到困惑,为什么会使用这种方法而不是通用的setter方法。

如果你有一个你不希望任何人设置的属性,那就是你的类。 这对于数据库ID来说非常方便。 内部类可以设置它,但你不希望任何其他人改变它。 所以你可以给他们读取权限,但不能写。

编辑:还有一点是,使用您展示的内容对自动属性很有帮助。 遗憾的是,对于自动属性,您无法仅指定get,以避免公开公开setter,只是将其设为私有。

编辑:只是想我会举一个例子。 自动属性非常适合干净,简洁的代码。 但是就像你展示的那样,你必须得到并设定一个限制。 所以在此之前,对于像你这样的房产来说:

 public class Test { private object thingy; public object Thingy { get { return thingy; } } } 

现在我们可以摆脱那种不必要的私人声明,但它需要两者。 所以私下来解决这个问题。

我知道这对解释来说太过分了,但不同的事情一直在我的脑海中浮现。

举个简单的例子; 它是制作“不可变的”对象(用于线程,状态等)的廉价方法。 但也可以在任何地方,客户端根本不需要分配它,或者不能信任它(正确地)分配它。

另一个例子可能是一个列表:

 public List Items {get;private set;} 

因为我们可能会调用obj.Items.Add()等,但我们很少会分配obj.Items = ... 但是,这个例子在构造函数中需要显式初始化,并且XmlSerializer讨厌它 – 对于我主要使用的列表诚实:

 private readonly List items = new List(); public List Items {get { return items;}} 

这解决了这两个问题。

另一个例子,对比:

 private readonly int foo; public int Foo {get{return foo;}} 

VS

 private readonly int foo; public int Foo {get{return foo;} private set {foo=value;}} 

这种模式在序列化中可能很有用,例如使用DataContractSerializer (添加了一些属性),因为许多序列化程序仍然会寻找私有访问器。 这避免了我们必须装饰我们的内部状态( foo ),但是给出了隐私的贴面

最终, 任何东西都可以绕过并通过reflection分配,因此私有set只是为了避免意外损坏数据。

私人使它成为一个只读的财产。 一个常见示例是,如果有多个类传递单个对象,则不希望其他类能够修改实例。

基本上,它是一个只读属性。 如果它是完整的(不是作为汽车财产),你只需要省略设置者。

两个大致相同的例子:

 class Foo1 { public int Id { get; private set; } public Foo1() { Id = lastId ++; } } class Foo2 { private int _id; // could be readonly public int Id { get { return _id; } } public Foo2() { _id = lastId ++; } } 

我已经看到这与设计一起使用:

 public class whatever { public string WhateverId { get; private set; } public static whatever Create(string whateverId) { return new whatever() { WhateverId = whateverId }; } } 

因此,您创建了任何类,但在创建之后,无法更改ID,因为它可能会破坏与其连接的内容。

私有集只提供了简单的初始化语法,我对某些场景有点喜欢它。

如果可以更改,也可以使用,但是在进行更改时需要对其进行管理

 public void SetWhateverId(string whateverId) { DisconnectAllCurrentWhateverIdReferences(); WhateverId = whateverId; ReconnectAllPreviousWhateverIdReferences(); } 

此语法允许您提供面向公众的属性,该属性对API的使用者显示为只读,但内部可以更改。 通过以这种方式自动实现,您可以避免编写样板代码,例如值的不同的setter或支持字段,并且如果在某些时候认为有必要,您可以在设计中留出空间来添加定制的设置算法。未来不必立即决定未来。

私有集对于简单的不可变值类型非常方便。

 struct Point { public int X { get; private set; } public int Y { get; private set; } public Point(int x, int y) { this = default(Point); X = x; Y = y; } } 

这只是来自自动属性的laziness 。 在自动属性出现之前,人们会实现getter并省略属性的setter,这些属性是只读的。

 public class Test { private /*readonly*/ Type _thingy; public Type Thingy { get { return _thingy; } } } 

希望C#5允许您仅使用getter创建自动属性 ​​- 因为这是每个人都想要的。 (他们也应该在自动道具中制作只读的制定者,我需要那么糟糕)

要回答一个常见场景可能会被使用的问题……在MVP模式中,如果你的模型公开了Presenter的一些属性,我会写

 public string Bazinga { get; private set; } 

现在,模型可以更改此值,但使用它的其他类不能。