一个具有私有setter方法的属性和一个没有setter方法的属性之间有什么区别?

5
如果我想定义一个只读属性,需要这样写:
public int MyProperty { get { //Code goes here } }

然而,微软的例子(以及我看到的其他一些例子)都是这样编写的:

但是:

public int MyProperty { get; private set; }

这两种写法有什么区别,我应该采用哪一种方式书写属性呢?

2
是的,在第二种情况下,它所属的类可以设置它的值。 - CRice
1
理解私有设置器 - Soner Gönül
5个回答

9

正如您在第二个示例中所看到的那样,您可以省略属性的实现。.NET将自动为该属性创建一个本地变量并实现简单的获取和设置。

public int MyProperty { get; private set; }

实际上等同于

private int _myProperty;

public int MyProperty { 
    get { return _myProperty; }
    private set { _myProperty = value; }
}

写作
public int MyProperty { get; }

完全不起作用,因为自动属性需要实现一个getter和一个setter,而

public int MyProperty { get; private set; }

留给您一个属性,可以返回任何int,但只能在当前类中更改。
public int MyProperty { get { ... } }

创建了一个只读属性。

问题是:你需要什么? 如果你已经在类内使用了成员变量,只想通过属性返回当前值,那么下列代码就可以实现:

public int MyProperty { get { return ...; }}

然而,如果您需要一个只读属性,它需要在您的代码中设置(但不是从其他类中设置),而且不需要显式地声明成员变量,那么您就必须采用private set方法。


8
public int MyProperty { get; } 这段代码并没有定义任何类型的属性,这是不合法的。 - Eric Lippert
@EricLippert 你是对的。我修改了我的答案来解决这个问题。 - Thorsten Dittmar
5
根据C#6的规定,public int MyProperty { get; } 是合法的代码。 - Mord Zuber
如果它永远不能被设置,那么它会返回什么? - Thorsten Dittmar
1
它只能在构造函数中设置。 - Daniel Forsyth

7

使用私有 setter,您只能在实例内部分配属性值。当属性没有 setter 时,您无法在任何地方设置其值。


4
如果您在属性中没有使用显式成员赋值,那么您至少需要声明一个private set才能设置该属性的值。否则,在编译时将会收到警告,告诉您无法为该属性分配值。
如果您使用了显式成员,则可以直接为该成员赋值,而不需要添加private set
private int member ;

public int MyProperty {
    get { return member; }
}

// ...

member = 2;
int anotherVariable = MyProperty; // anotherVariable == 2

在你的例子中,对我来说使用私有 setter 实际上没有任何意义。如果我有一个可以更改的私有成员,那么为什么还需要私有 setter 呢?唯一的原因是如果设置属性做了更多的事情而不仅仅是更改私有成员。 - Thorsten Dittmar
@ThorstenDittmar 你说得对。为了清晰起见,删除了私有设置。感谢您指出这一点。 - xlecoustillier

2
public int MyProperty
{
  get
  {
    // Your own logic, like lazy loading
    return _myProperty ?? (_myProperty = GetMyProperty());
  }
}

如果您需要自己的逻辑来访问属性,特别是当您需要惰性加载属性时,仅具有getter的属性非常有用。

public int MyProperty { get; private set; }

如果您需要属性不能从外部更改但仍需在类内部维护,具有私有设置器的属性非常有用。

在两种情况下,您都可以拥有实际值的支持数据字段,但在前者中,您必须自己维护该字段,在后者中,生成的代码会为您维护该字段。


1

使用反射访问对象时会有所不同。

public class Foo
{
    public string Bar { get; private set; }
}

// .....
    internal static void Main()
    {

        Foo foo = new Foo();
        foo.GetType().GetProperty("Bar").SetValue(foo, "private?", null);
        Console.WriteLine(foo.Bar);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接