了解私人制定者

Den*_*ene 82 c#

我不明白是否需要拥有以C#2开头的私人制定者.

为我设置一个setter方法是让用户在该类中设置一些变量.在这样做时,我们不会将变量直接暴露给用户.相反,我们让他们通过这种公共setter方法来做到这一点.

这对我来说是使用"封装".有一些争论声称私人制定者会允许你应用封装.

我是不是通过使用公共setter方法使用封装?为什么我们需要私人制定者?

不可变类和具有私有setter的类有什么区别?

ktu*_*nik 234

按道理.

私有设置器的存在是因为您可以使用自动属性:

public int MyProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

如果你想让它成为只读,你会怎么做?

public int MyProperty { get; }
Run Code Online (Sandbox Code Playgroud)

哦废话!! 我不能从我自己的班级访问它; 我应该像普通属性一样创建它:

private int myProperty;
public int MyProperty { get { return myProperty; } }
Run Code Online (Sandbox Code Playgroud)

嗯......但我失去了"自动财产"功能......

public int MyProperty { get; private set; }
Run Code Online (Sandbox Code Playgroud)

AHHH ..那更好!!

  • @ktutnik感谢您按照自己的方式做到这一点.现在对我来说也很有意义! (3认同)
  • 使用 c# 6 添加 #tsemer 的答案,`{get; }` 不等于 `{ get; 私人套装;}`。对于第一种方式,“property.GetSetMethod(true)”返回“null”,后一种方式返回“true”。这让我很惊讶。 (3认同)
  • 谢谢。这又说得通了 (2认同)
  • 非常有说服力的答案. (2认同)
  • "哦,废话!! 我不能从我自己的类中访问它.从C#6.0开始,这只在初始化阶段之外才是真的.请参阅我的答案http://stackoverflow.com/a/34223746/198797 (2认同)

Chr*_*isF 36

如果您具有只读属性并且不希望显式声明支持变量,则私有setter非常有用.

所以:

public int MyProperty
{
    get; private set;
}
Run Code Online (Sandbox Code Playgroud)

是相同的:

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}
Run Code Online (Sandbox Code Playgroud)

对于非自动实现的属性,它为您提供了一种类中设置属性的一致方法,这样如果您需要验证等,您只能将它放在一个位置.

为了回答你的最后一个问题,MSDN对私人制定者说:

但是,对于只封装一组值(数据)并且几乎没有行为的小类或结构,建议通过将set访问器声明为private来使对象不可变.

Auto Implemented属性的MSDN页面

  • 很抱歉,由于拥有私人设置器,我仍然没有看到附加值。如果我们不想让 setter 暴露,我们就只有 getter。如果我们想添加验证器,我们可以有一个公共设置器并向其添加验证。为什么我们需要一个不可访问的 setter?我的理解就像“开这辆车,但你不会开它”如果我无论如何都不会开的话你为什么要给我这辆车 (2认同)

Eri*_*sch 17

这很简单.私有setter允许您创建只读公共或受保护的属性.

而已.这是唯一的原因.

是的,您可以通过仅指定getter来创建只读属性,但是使用auto-implmeneted属性需要指定get和set,因此如果您希望自动实现的属性是只读的,则必须使用私人二传手.没有其他办法可以做到这一点.

确实,专用setter不是专门为自动实现的只读属性创建的,但由于其他原因,它们的使用更为深奥,主要围绕只读属性以及反射和序列化的使用.

  • 谢谢"如果你想让一个自动实现的属性是只读的,你必须使用私有的setter".这对我来说很有意义 (2认同)

tse*_*mer 14

随着C#6.0的引入和自动属性初始化程序的语法,仅在初始化时设置的属性不再需要私有setter,无论是内联还是构造函数.

这些新语法现在编译:

内联初始化属性

public class MyClass1 {
  public string MyProperty { get; } = "Aloha!"
}
Run Code Online (Sandbox Code Playgroud)

构造函数初始化属性

public class MyClass2 {
  public string MyProperty { get; }

  public MyClass2(string myProperty) {
    MyProperty = myProperty;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @Ziggler,的确不是。OP也不问。他只是不了解拥有它们的需要。答案:“在这种情况下,您不再需要它们”。 (3认同)

小智 5

我不了解需要以C#2开头的私有设置器。

例如,发票类允许用户从Items属性中添加或删除项目,但不允许用户更改Items引用(即,用户无法将Items属性分配给另一个项目列表对象实例)。


public class Item
{
  public string item_code;
  public int qty;

  public Item(string i, int q)
  {
    this.item_code = i;
    this.qty = q;
  }
}

public class Invoice
{
  public List Items { get; private set; }

  public Invoice()
  {
    this.Items = new List();
  }
}

public class TestInvoice
{
  public void Test()
  {
    Invoice inv = new Invoice();
    inv.Items.Add(new Item("apple", 10));

    List my_items = new List();
    my_items.Add(new Item("apple", 10));

    inv.Items = my_items;   // compilation error here.
  }
}
Run Code Online (Sandbox Code Playgroud)