在某些情况下,我在我的类顶部声明成员变量,然后声明一个属性来访问或设置该成员变量,但我问自己,如果该变量只是被访问,那么该属性是否必要从类中设置而不是在其他地方设置,因此使用属性访问和设置成员变量的优势是什么,而不是直接将其直接添加到成员变量本身。这是一个例子:
public class Car
{
int speed; //Is this sufficient enough if Car will only set and get it.
public Car(int initialSpeed)
{
speed = initialSpeed;
}
//Is this actually necessary, is it only for setting and getting the member
//variable or does it add some benefit to it, such as caching and if so,
//how does caching work with properties.
public int Speed
{
get{return speed;}
set{speed = value;}
}
//Which is better?
public void MultiplySpeed(int multiply)
{
speed = speed * multiply; //Line 1
this.Speed = this.Speed * multiply; //Line 2
//Change speed value many times
speed = speed + speed + speed;
speed = speed * speed;
speed = speed / 3;
speed = speed - 4;
}
}
在上面,如果我没有设置Speed属性并获得变速,我决定将int speed更改为int spd,我将不得不将速度更改为spd,但是,如果我使用诸如Speed之类的属性来设置和获取速度,我将只需要在属性的get和set中将spd的速度更改为spd,所以在我的MutilplySpeed方法中,像上面这样的东西.Speed = this.Speed + this .Speed + this.Speed不会破坏。
答案 0 :(得分:23)
如果变量是private
,我通常不会为它创建属性。如果它以任何方式暴露在类型之外,我总是通过一个属性暴露它:出于不同的原因:
此外,如果字段是通过属性公开的,我总是通过属性访问它,即使在类中也是如此。
<强>更新强>
为了回应您更新的代码示例:在此处代码设计需要考虑许多事项。
一个典型的建议(我发现非常好)是“为了清晰起见,为性能测试”。这意味着当你编写代码时,首先要考虑的是代码在查看代码时是否清楚。这通常(但并非总是)比代码的原始速度更重要。在确定获得它的位置时写入速度优化。访问一个属性比直接读取字段要慢一些,但在大多数情况下,差异可以忽略不计(如果可以测量的话)。
Atomicity 可能是个问题。根据您的代码示例,我们有字段speed
,该字段通过属性Speed
公开显示。如果方法MultiplySpeed
需要对值执行多次更新,那么在计算正在进行时,这些中间值将在不同时间通过Speed
属性提供。无论您是直接更新字段还是通过属性更新字段,都是如此。在这种情况下,最好先将值放入局部变量,将其用于计算,并在完成后将该变量的值赋回属性。
最后,其他副作用。可能更改Speed
的值应该引发事件(例如SpeedChanged
)。在这种情况下,在计算完成之前不进行更新也是一个好主意。
我喜欢将该属性视为合同,将该字段视为实现。需要该值的任何人(除了我的类型的核心)都应该使用合同。只有在有充分理由绕过合同时才能依靠实施。
是的,如果你封装了对属性中字段的访问权限,那么自然地更改字段的名称将需要更少的更新(也许字段的名称变得不那么重要了。)
我希望这是有道理的,而且不是太偏离主题;)
答案 1 :(得分:8)
我同意Frederik's的答案。有一件事使得遵循他的建议稍微减少工作就是使用自动属性。这些只是自动生成标准getter / setter逻辑的属性。您没有得到任何验证,但您可以随后用标准的自动属性替换自动属性。这种替换不是一个重大变化。
这里我用自动属性替换了示例中的Speed属性。请注意,成员变量消失,您的类必须通过属性访问它。
public class Car
{
public Car(int initialSpeed)
{
Speed = initialSpeed;
}
public int Speed { get; set; }
public void MultiplySpeed(int multiply)
{
Speed *= multiply;
}
}
您还可以使用另一种名为“get with private set”的风格。这意味着getter是公共的,但setter是私有的。你可以这样定义:
public int Speed { get; private set; }
关于this.
前缀的问题,通常无关紧要。唯一重要的是你定义了一个方法参数或局部变量,其名称与成员变量相同。然后,您可以使用this
来访问成员变量。
答案 2 :(得分:1)
验证之类的事情可以在一个地方覆盖。该成员是封装的,您需要担心验证和其他类的其他事情。
在您当前的场景中,它确实没有什么区别,但是当您需要更改变量或需要添加行为时,使用属性会更容易,因为您只需要一个地方需要更改它。
答案 3 :(得分:1)
它不会添加缓存,但它确实允许一致的界面。
想象一下,你必须通过在将来添加一个常量来提高速度。使用成员变量将很困难,因为属性允许这种操作。
同样在类的内部,您应该再次访问该属性以保持一致性(想象一下您有一个直接访问成员变量的类的上述场景)。
答案 4 :(得分:1)
我所知道的唯一真正原因是是否从装配体外部访问该区域。在这种情况下,如果您想为该字段添加灯光功能(可能设置脏标志或验证更改),您必须将其更改为一个属性,该属性会更改调用程序集查看它的方式,这也需要重建。在极少数情况下,您可能会发现您无法控制该程序集,那么您就会遇到问题。
不要让OO狂热者告诉你使用公共字段是错误的,尽管我可能会同意自动属性使得这个论点有点没有实际意义。
答案 5 :(得分:1)
事实上,如果没有额外的逻辑,公开声明的字段和具有私有后备存储的公共属性之间没有太大区别。话虽如此,仍然认为使用属性是最佳做法。
在每个人都向我推断可扩展性之前,请记住,如果以后需要添加功能,可以使用属性保留名称,并为后备存储引入新名称,这样就不会发生重大变化。
答案 6 :(得分:0)
有一件事你忘了提及,属性会帮助你扩展你的课程。
如果您的类设计得当,基类中的变量应为private
。没有实际属性public
属性。您无法从扩展类中访问这些私有变量。我们正在谈论公共与私人,我不会因为某种原因而受到保护:)。
值得一提的是:
这些只是一些常见的事情(我的大部分都是2美分)。
答案 7 :(得分:0)
在我看来,语言设计被打破了。不应该有两种方法来处理那么多语义重叠的事情。属性/字段应该无缝地提供两种方法的好处,具体取决于它们的使用方式。如果程序对Property功能的使用最少,则它们的行为应与field相同。此外,不需要声明空的get;并设定;这种情况下的方法。这些差异让我觉得是人为的。
这是一门很棒的语言;而且大部分都很干净。这并不意味着它不应该在“下一次”改进。