访问您自己类中的成员:是否使用(自动)属性?

我已经将这个“问题”创建为社区维基,因为没有正确或错误的答案。 我只想知道社区对这个具体问题的看法。

当你有一个带有实例变量的类,并且你还创建了只是这些实例变量的getter和setter的属性时,你应该使用你自己的类中的属性,还是应该总是使用实例变量?

在C#3.0中拥有自动属性使得这个决定变得更加困难。

使用属性:

public class MyClass { private string _name; // could be an auto-property of-course public string Name { get { return _name; } set { _name = value; } } public void Action() { string localVar = Name; // ... Name = "someValue"; // ... } } 

使用实例变量:

 public class MyClass { private string _name; public string Name { get { return _name; } set { _name = value; } } public void Action() { string localVar = _name; // ... _name = "someValue"; // ... } } 

(对于那些讨厌会员前缀的人,我道歉)

就个人而言,我总是使用后者(实例变量),因为我觉得属性应该只用于其他类,而不是你自己。 这就是为什么我主要远离自动财产。

当然,当属性设置器(或getter)不仅仅包装实例变量时,事情会发生变化。

是否有令人信服的理由选择其中一个?

这是一个经常被问到的问题。 这是我的文章,描述了一些问题:

http://blogs.msdn.com/ericlippert/archive/2009/01/14/automatic-vs-explicit-properties.aspx

我也总是使用实例变量。 原因是因为属性可能正在执行诸如validation参数(如在setter中)而不是null或不为空的东西。 如果您在类代码中使用变量,则无需经历这些检查的额外开销(假设您知道变量值有效)。 这些属性也可能正在执行其他事情(例如,日志记录),这些对于公共API很重要,但对于内部用法则不重要,所以再次,最好避免开销,只是在我看来使用实例变量。

我认为如果代码使用自己的公共接口,则更改内部实现会变得更加困难。

难以解释但考虑这些表达式:

 mTotalPrice = mPrice * mQuantity; mTotalPrice = Price * Quantity; 

如果我需要更改内部以用€而不是$表示所有价格(不影响仍然使用$的公共接口),在第二个表达式中该怎么做?

一种解决方案是通过添加与属性更改相反的方式使表达式更复杂。

 mTotalPrice = Price / Rate * Quantity 

另一种解决方案是开始使用私有字段。

 mTotalPrice = mPrice * Quantity 

最后,您将获得私人和公共用途。 获得一致使用的唯一方法是始终使用私有字段。

我也不喜欢为成员添加前缀,但实际上我发现我可以意外地写出这样的内容,直到运行时才发现它。 哪种诱惑让我避免使用他们不需要的属性……但我现在仍然这样做!

 Public String MyString { { get { return this.MyString; } } //<== Stack Overflow { set { this.myString = value; } } } private String myString; 

我认为这两种方法没有区别。

自动实现的属性只是访问以任何方式创建的私有成员的快捷方式。

来自MSDN的示例:

 class Customer { // Auto-Impl Properties for trivial get and set public double TotalPurchases { get; set; } public string Name { get; set; } public int CustomerID { get; set; } // Constructor public Customer(double purchases, string name, int ID) { TotalPurchases = purchases; Name = name; CustomerID = ID; } // Methods public string GetContactInfo() {return "ContactInfo";} public string GetTransactionHistory() {return "History";} // .. Additional methods, events, etc. } 

99%的时候我使用属性而不是实例变量。 在过去,我使用了很多使用实例变量的代码,当有一个与该变量相关的错误时,我不得不在引用它的每一行代码上放置一个断点。

我决定使用属性(公共或私有)来包装实例变量。 这样做意味着我只需要在属性的getter / setter中放置一个断点,如果我需要调试实例变量的问题,而不是(可能)在代码中分散了很多断点。