Answers:
我将更进一步,将其归结为3个案例。尽管每个都有不同,但这是我在C#编程中大部分时间使用的规则。
在情况2和3中,请始终转到属性访问器(而不是字段变量)。在第一种情况下,您不必选择此选项。
1.)不可变属性(传递给构造函数,或在构造时创建)。在这种情况下,我使用具有只读属性的字段变量。我选择此方法而不是私有设置程序,因为私有设置程序不能保证不变性。
public class Abc
{
private readonly int foo;
public Abc(int fooToUse){
foo = fooToUse;
}
public int Foo { get{ return foo; } }
}
2.)POCO变量。可以在任何公共/私有范围内获取/设置的简单变量。在这种情况下,我只会使用自动属性。
public class Abc
{
public int Foo {get; set;}
}
3.)ViewModel绑定属性。对于支持INotifyPropertyChanged的类,我认为您需要一个私有的后备字段变量。
public class Abc : INotifyPropertyChanged
{
private int foo;
public int Foo
{
get { return foo; }
set { foo = value; OnPropertyChanged("foo"); }
}
}
通常,我会说分配给构造函数中的字段并在其他地方使用该属性。这样,如果有人向该属性添加功能,您将不会在任何地方错过它。
当然,这不是性能因素。优化器将为您内联一个简单的get或set,最终的MSIL代码可能相同。
好吧,直截了当的方法就是将其分配给变量本身,因为无论如何,您都在类的方法内部,并且您可以控制类的行为。
但是关于属性的全部要点是它们将变量抽象掉了。就像您的示例中那样的简单属性仅对简单的公共成员变量完全没有用,而属性通常会(或应该)在其getter和setter内做其他事情。而且,如果您希望在更改类内部的属性时自动完成这些操作,那么在属性设置行为发生变化时不必更改每个变量分配就可以更轻松地使用属性而不是变量。
您只需要从概念上对此进行推理。该属性实际上是用于访问对象的某些内部状态的句柄,该状态可能由多个成员变量组成。因此,您必须问自己:是否只想更改底层内部状态(或仅更改其一部分),还是要整体更改表示该状态的抽象属性,而且大多数情况下确实是后者,因为您通常希望对象始终具有一致的状态。
通常,由您决定在获取/设置属性时应如何处理属性及其后备字段。
通常,只是为了在代码之间保持一致,您应该在可用的公共访问器上使用公共访问器。这样您就可以以最少的代码更改来重构。如果需要将执行此设置的方法从类中删除,并放置在不再有后备字段的其他地方(例如基类),那么谁在乎呢?无论使用班级本身在哪里完成工作,您都在使用可用的东西。在大多数情况下,后备字段是实现细节。班上没有人不应该知道它的存在。
我可以想到的主要情况是,当访问器具有不想运行的其他逻辑(验证或更新类中的其他状态信息)时,应该使用支持字段而不是属性访问器。一个对象的初始填充就是一个例子。您可能有一个使用两个属性值来计算第三个属性值的类,该属性值也存储在备用字段中(出于持久性原因)。在初始化给定对象的新副本时,如果给定了来自DB的数据,则如果未设置其他所需的值,则每个都重新计算第三个值的属性访问器可能会抱怨。通过使用备用字段设置这两个(或三个)属性的初始值,可以绕过验证/计算逻辑,直到实例处于足够一致的状态以使逻辑正常工作。
始终使用有意义的选项。是的,我知道听起来很虚假,以至于无法回答。
属性的重点是提供一个接口,您可以通过该接口安全地访问数据模型。对于大多数情况,您始终希望通过该界面安全地访问数据模型,例如:
public Foo Bar
{
get { return _bar; }
set { _bar = doSomethingTo(value); }
}
但是在其他情况下,您可能只是使用属性作为数据模型的视图:
public Double SomeAngleDegrees
{
get { return SomeAngleRadians * 180 / PI; }
set { SomeAngleRadians = value * PI / 180; }
}
如果使用的弧度形式有意义SomeAngle
,则一定使用它。
最后,一定要喝自己的酷儿食品。您的面向公众的api应该具有足够的弹性以在内部工作。