我已经看过很多使用类似代码编写的示例代码(请原谅这是多么可怕的罐头):
public class Test
{
public object Thingy { get; private set; }
}
不幸的是,这些例子从未真正解释为什么'set'被设置为私有。所以,我只是想知道是否有一个好的,常见的例子可以向我说明为什么会使用这样的东西。
我有点看到 - 除了设置该字段外,还可以运行该属性来处理一些额外的逻辑。我只是对如何调用它感到困惑,为什么会使用这种方法而不是通用的setter方法。
答案 0 :(得分:24)
如果你有一个你不希望任何人设置的属性,那就是你的班级。这对于数据库ID来说非常方便。内部类可以设置它,但你不希望任何其他人改变它。所以你可以给他们读取权限,但不能写。
编辑:还有一点是,使用您展示的内容对自动属性很有帮助。不幸的是,对于自动属性,你不能只指定get,以免公开暴露一个setter它只是私有。
编辑:我想我会举一个例子。自动属性非常适合干净,简洁的代码。但是就像你展示的那样,你必须得到并设定一个限制。所以在此之前,像你所展示的房产一样:public class Test
{
private object thingy;
public object Thingy
{
get { return thingy; }
}
}
现在我们可以摆脱那种不必要的私人声明,但它需要两者。所以私下来解决这个问题。
我知道这对解释来说太过分了,但不同的事情一直在我脑海中浮现。
答案 1 :(得分:9)
作为一个简单的例子;它是一种制作“不可变的”对象的廉价方法(用于线程,状态等)。但是,客户只需不应该需要分配它,或不能信任来分配它(正确)。
另一个例子可能是一个列表:
public List<Foo> Items {get;private set;}
因为我们可能会调用obj.Items.Add()
等,但我们很少分配obj.Items = ...
。但是,这个例子在构造函数中需要显式初始化,而XmlSerializer
讨厌它 - 对于我主要使用的列表是诚实的:
private readonly List<Foo> items = new List<Foo>();
public List<Foo> 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
),而是为set
提供隐私单板。
最终任何可以绕过并通过反射分配,因此私有set
仅用于避免意外数据损坏。
答案 2 :(得分:4)
私有使其成为只读属性。一个常见的例子是,如果你有多个类传递一个对象,你不希望另一个类能够修改实例。
答案 3 :(得分:2)
基本上,它是一个只读属性。如果它是完整的(不是作为汽车财产),你只需要省略设置者。
两个大致相同的例子:
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 ++;
}
}
答案 4 :(得分:2)
我已经看到这与设计一起使用:
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();
}
答案 5 :(得分:1)
此语法允许您提供面向公众的属性,该属性对API的使用者显示为只读,但内部可以更改。通过这种方式自动实现,您可以避免编写样板代码,例如不同的setter或值的后备字段,并且如果在某些时候认为有必要,您可以在设计中留出空间来添加定制的设置算法。未来不必立即决定。
答案 6 :(得分:1)
私有集对于简单的不可变值类型非常方便。
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;
}
}
答案 7 :(得分:0)
这只是来自自动属性的laziness
。在自动属性出现之前,人们会实现getter并省略属性的setter,这些属性是只读的。
public class Test
{
private /*readonly*/ Type _thingy;
public Type Thingy { get { return _thingy; } }
}
希望C#5允许您仅使用getter创建自动属性 - 因为这是每个人都想要的。 (他们也应该在自动道具中制作只读的制定者,我需要那么糟糕)
答案 8 :(得分:0)
回答可能会使用此常见情况的问题...... 在MVP模式中,如果您的模型为Presenter公开了一些属性,我会写
public string Bazinga { get; private set; }
现在,模型可以更改此值,但使用它的其他类不能。