Properties vs Methods
快速问题:什么时候决定使用属性(在C中),什么时候决定使用方法?
我们正忙于进行这场辩论,并发现了一些值得商榷的领域,即我们是否应该使用属性或方法。一个例子是:
1 2 3 4 | public void SetLabel(string text) { Label.Text = text; } |
在示例中,
我将接受最一般和最全面的答案,但这也涉及到我给出的例子。
从开发类库的设计指南的"属性和方法之间的选择"部分:
In general, methods represent actions and properties represent data. Properties are meant to be used like fields, meaning that properties should not be computationally complex or produce side effects. When it does not violate the following guidelines, consider using a property, rather than a method, because less experienced developers find properties easier to use.
是的,如果您所做的只是获取和设置,请使用属性。
如果您正在做一些可能影响多个数据成员的复杂操作,则方法更合适。或者如果getter接受参数,或者setter接受的参数多于value参数。
中间是一个灰色区域,在那里线条可能有点模糊。没有硬性和快速的规则,不同的人有时会不同意某个东西应该是属性还是方法。重要的是要(相对地)与你如何做(或者你的团队如何做)保持一致。
它们在很大程度上是可互换的,但它是向用户发出的一种属性信号,表示实现相对"简单"。哦,语法也比较清楚。
一般来说,我的哲学是,如果您开始编写一个以get或set开头的方法名,并分别接受零个或一个参数,那么它就是一个属性的主要候选者。
如果要设置对象的实际属性,则使用属性。
如果正在执行任务/功能,则使用方法。
在您的示例中,它是一个正在设置的确定属性。
但是,如果您的功能是追加标签,那么您将使用一个方法。
属性是一种从对象中插入或检索数据的方法。它们在类中的变量或数据上创建一个抽象。它们类似于Java中的吸气剂和定位器。
方法封装操作。
一般来说,我使用属性公开数据的单个位,或者类上的小计算,比如增值税。这是从购物车中的商品数量及其成本得出的。
我在创建操作时使用方法,比如从数据库中检索数据。任何具有活动部件的操作都可以作为方法的候选者。
在您的代码示例中,如果需要在包含类的外部访问它,我将把它包装在一个属性中:
1 2 3 4 5 | public Label Title { get{ return titleLabel;} set{ titleLabel = value;} } |
设置文本:
1 | Title.Text ="Properties vs Methods"; |
如果我只是设置标签的文本属性,我会这样做:
1 2 3 4 5 | public string Title { get{ return titleLabel.Text;} set{ titleLabel.Text = value;} } |
设置文本:
1 | Title ="Properties vs Methods"; |
对称属性是对象的属性。方法是对象的行为。
标签是一个属性,使其成为一个属性更有意义。
对于面向对象编程,您应该清楚地了解什么是行为的一部分,什么仅仅是属性。
汽车颜色、型号、品牌
汽车有颜色、型号和品牌属性,因此使用set color或set model方法是没有意义的,因为我们对称地不要求汽车设置自己的颜色。
因此,如果您将属性/方法案例映射到现实中的对象,或者从symantic的角度来看它,那么您的困惑将真正消失。
通过对msdn的搜索,我发现了一个关于属性和方法的参考,它为创建方法提供了一些很好的指导:
- The operation is a conversion, such as
Object.ToString .- The operation is expensive enough that you want to communicate to the
user that they should consider caching
the result.- Obtaining a property value using the get accessor would have an observable
side effect.- Calling the member twice in succession produces different results.
- The order of execution is important. Note that a type's properties should
be able to be set and retrieved in any
order.- The member is static but returns a value that can be changed.
- The member returns an array. Properties that return arrays can be
very misleading. Usually it is
necessary to return a copy of the
internal array so that the user cannot
change internal state. This, coupled
with the fact that a user can easily
assume it is an indexed property,
leads to inefficient code.
你只需要看看这个名字……""财产"。这是什么意思?词典在许多方面对其进行了定义,但在本例中,"事物的一个基本的或独特的属性或质量"最合适。
想想行动的目的。实际上,你是在改变或找回"一个基本的或独特的属性"吗?在您的示例中,您使用函数来设置文本框的属性。看起来有点傻,不是吗?
属性实际上是函数。它们都编译成getxxx()和setxxx()。它只是将它们隐藏在句法的糖分中,但糖分为这个过程提供了语义意义。
考虑属性之类的属性。汽车有许多特性。颜色、MPG、型号等。并非所有属性都是可设置的,有些属性是可计算的。
同时,一种方法就是行动。getcolor应为属性。getfile()应该是一个函数。另一个经验法则是,如果它不改变对象的状态,那么它应该是一个函数。例如,calculatePintOnthDigit(n)应该是一个函数,因为它实际上并没有改变它所连接的数学对象的状态。
这可能有点杂乱无章,但归根结底,它决定了你的对象是什么,以及它们代表什么。如果你不知道它是否应该是一个属性或函数,也许这不重要。
属性的另一大优点是,在调试期间可以在Visual Studio中看到属性的值。
属性应该只进行简单的设置并得到一个衬线。任何更多的东西,它真的应该转移到一个方法。复杂代码应该总是在方法中。
我更喜欢使用带有1个参数的添加/设置方法的属性。如果参数更多,请使用方法。
我只将属性用于变量访问,即获取和设置单个变量,或获取和设置控件中的数据。只要需要/执行任何类型的数据操作,我就使用方法。
就设计而言,属性代表类对象的数据或属性,而方法则是类对象的动作或行为。
在.NET中,使用属性还有其他含义:
- 属性用于数据绑定,而get_u/set_u方法不用于数据绑定。
- XML序列化用户属性作为序列化的自然机制。
- 属性由PropertyGrid控件和Intern ICustomTypeDescriptor访问,如果您正在编写自定义库,则可以有效地使用这些属性。
- 属性由属性控制,可以明智地使用它来设计面向方面的软件。
对物业使用的误解(IMHO):
- 用于显示小计算:ControlDesigner.SelectionRules的get块运行到72行中!!
- 用于公开内部数据结构:即使属性未映射到内部数据成员,如果它是类的属性,也可以将其用作属性。viceversa,即使它是类属性的一个属性,也不建议返回类似数组的数据成员(相反,方法用于返回成员的深度副本)。
在这里的示例中,它可以被编写,更多的业务含义是:
1 2 3 4 | public String Title { set { Label.Text = text; } } |
属性非常好,因为只要它们具有访问权限,就可以在Visual Studio的可视化设计器中访问它们。
如果您只是在设置和获取,或者可能是一些无法访问大量代码的验证,则可以使用它们。请小心,因为在验证期间创建复杂对象并不简单。
其他方法都是首选方法。
不仅仅是语义。使用不适当的属性开始在Visual Studio Visual Designer中发生奇怪。
例如,我在一个类的属性中得到一个配置值。配置类实际上打开一个文件并运行一个SQL查询来获取该配置的值。这在我的应用程序中导致了一些问题,在这些问题中,配置文件将被Visual Studio本身而不是我的应用程序打开和锁定,因为它不仅读取配置值,还写入配置值(通过setter方法)。为了解决这个问题,我只需要把它改成一种方法。
下面是一套关于何时使用属性和比尔·瓦格纳的方法的好指南。
- 当所有这些都为真时使用属性:getter应该很简单,因此不太可能抛出异常。注意,这意味着没有网络(或数据库)访问。两者都可能失败,因此会引发异常。
- 他们不应该互相依赖。请注意,这将包括设置一个属性并使其影响另一个属性。(例如,设置first name属性将影响组成first name+last name属性的只读fullname属性,这意味着存在这样的依赖关系)
- 它们应该可以按任何顺序设置
- 吸气剂没有明显的副作用。注意,本指南并不排除属性中某些形式的延迟评估。
- 方法必须始终立即返回。(请注意,这排除了进行数据库访问调用、Web服务调用或其他类似操作的属性)。
- 如果成员返回数组,则使用方法。
- 对getter的重复调用(不需要干预代码)应返回相同的值。
对setter的重复调用(具有相同的值)不应与单个调用产生任何差异。
get不应返回对内部数据结构的引用(请参见第23项)。一个方法可以返回一个深度拷贝,并且可以避免这个问题。
*摘自我对一个重复问题的回答。
这很简单。
1:如果希望在字段中存储数据之前验证数据,请使用属性。因此,通过这种方式,属性为字段提供封装。因为如果您离开您的字段,公共最终用户可能会根据您的业务要求分配任何可能有效或可能无效的值,例如年龄应大于18岁。所以在值存储相应字段之前,我们需要检查它的有效性。通过这种方式,属性表示数据。
2:如果您想执行一些操作,比如提供一些数据作为参数,并且您的方法正在根据提供的值进行一些处理,并将处理后的值作为输出返回,请使用方法。或者您希望通过此计算更改某些字段的值。"以这种方式,方法表示动作"。
我来自爪哇A我用得到…设置…方法。
当我编写代码时,我不会问自己:"访问这些数据很简单,或者需要一个繁重的过程?"因为事情会发生变化(今天重新获得这个属性很简单,明天可能需要一些或繁重的过程)。
今天我有一个方法setage(int age)tomonrow我也将有方法setage(date birthdate)计算使用出生日期的年龄。
我对get和set中的编译器转换属性非常失望,但不考虑get…并设置…方法相同。