在C#中私密'设置' - 在我周围缠绕我的大脑时遇到困难

时间:2010-07-22 20:33:05

标签: c# private

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

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

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

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

9 个答案:

答案 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; }

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