属性与方法


135

快速提问:您何时决定使用属性(在C#中)以及何时决定使用方法?

我们正忙于这场辩论,并发现了我们应该使用财产还是方法值得商de的地方。一个例子是这样的:

public void SetLabel(string text)
{
    Label.Text = text;
}

在示例中,Label是ASPX页面上的控件。是否有一个原则可以支配决策(在这种情况下)是将其设为方法还是属性。

我将接受最普遍,最全面的答案,但这也涉及到我给出的示例。


2
-1这个问题已经被问过并回答过:stackoverflow.com/questions/164527/…–
元素

方法/领域/财产的优缺点可能引起长期争论。属性的一些一般用法:当您想要私有/保护字段但同时又要公开它们时。另一个用途是不仅具有语句,而且还具有表达式(如果需要,可以进行操作)甚至if()检查(按照MSDN)。但这很棘手,因为用户并不总是知道访问变量(属性)(即代码不可用)背后的处理成本,并且出于严格的原因,必须对属性进行基准测试。哦,还有一个“奖励”,您不能将指针与属性一起使用。
mireazma '16

Answers:


145

从“开发类库的设计准则”的“ 属性和方法之间选择”部分中:

通常,方法代表动作,属性代表数据。属性应像字段一样使用,这意味着属性不应在计算上复杂或不会产生副作用。如果它没有违反以下准则,请考虑使用属性而不是方法,因为经验不足的开发人员会发现更易于使用的属性。


3
虽然我大部分都同意,但我认为关于副作用的部分是不正确的。例如,“颜色”通常是对象的属性,并且具有明显的副作用(更改对象的颜色)。更改属性具有更改对象状态的明显副作用。
Erik Funkenbusch 09年

46
变色的神秘男子是理想的效果,而不是副作用。副作用是主要动作中不打算使用的。
穆罕默德·哈桑·汗

2
@Mystere Man:definelty改变颜色不是副作用,我完全同意这个答案
Ahmed Said

2
“由于经验不足的开发人员发现属性更易于使用。” -正如我所见,这是公开属性的唯一原因。但是我说的对吗?
2011年

2
属性与方法的内部实现有什么区别?每当使用属性时,是否会将任何东西压入调用堆栈?如果没有,该如何处理?
Praveen

57

是的,如果您要做的只是获取和设置,请使用属性。

如果您要执行可能会影响多个数据成员的复杂操作,则使用一种方法更为合适。或者,如果您的getter使用参数,或者您的setter使用的不是值参数。

中间是灰色区域,线条可能会有些模糊。没有一成不变的规则,不同的人有时会不同意某事应该是属性还是方法。重要的是要(相对)与您的操作方式(或团队的操作方式)保持一致。

它们在很大程度上是可以互换的,但是属性向用户发出信号,表示实现相对“简单”。哦,语法更简洁了。

一般来说,我的理念是,如果您开始编写以get或set开头并分别采用零个或一个参数的方法名称,则它是属性的主要候选对象。


1
不赞成投票。这是不正确的。getter或setter的复杂性封装在getter / setter代码中。它的复杂程度根本没有关系,也不会“影响多个数据成员”。确实,非标准或多个参数将需要一种方法,但否则此答案将不准确。
Hal50000

第一句话解释了所有内容。太棒了
SWIIWII

13

属性是一种从对象插入或检索数据的方法。它们在类中的变量或数据上创建抽象。它们类似于Java中的getter和setter。

方法封装了一个操作。

通常,我使用属性来显示数据的单个位,或对类进行小的计算,例如营业税。从商品数量及其在购物车中的成本得出。

创建操作时,我会使用方法,例如从数据库中检索数据。任何具有活动部分的操作都是方法的一种选择。

在您的代码示例中,如果需要在包含类的外部访问它,则将其包装在一个属性中:

public Label Title 
{
   get{ return titleLabel;}
   set{ titleLabel = value;}
}

设置文字:

Title.Text = "Properties vs Methods";

如果我只设置Label的Text属性,这就是我的方法:

public string Title 
{
   get{ return titleLabel.Text;}
   set{ titleLabel.Text = value;}
}

设置文字:

Title = "Properties vs Methods";

12

如果要设置对象的实际属性,则可以使用属性。

如果要执行任务/功能,则可以使用一种方法。

在您的示例中,这是一个确定的属性。

但是,如果您的功能是AppendToLabel,那么您将使用一种方法。


11

在MSDN中进行搜索时,我找到了关于“ 属性与方法”的参考,该参考为创建方法提供了一些很好的指导:

  • 该操作是一次转换,例如 Object.ToString
  • 该操作非常昂贵,以至于您希望与用户进行交流,使他们应该考虑将结果缓存。
  • 使用get访问器获取属性值会产生明显的副作用。
  • 连续两次呼叫成员会产生不同的结果。
  • 执行顺序很重要。请注意,类型的属性应该能够以任意顺序设置和检索。
  • 该成员是静态的,但返回可以更改的值。
  • 成员返回一个数组。返回数组的属性可能会非常令人误解。通常,必须返回内部阵列的副本,以便用户无法更改内部状态。这加上用户可以轻松地认为它是索引属性的事实,导致代码效率低下。

我同意,只要适用就行。但是我是对的,在WPF中通过XAML绑定使用属性除了在setter中执行适当的操作外别无选择吗?(尤其是针对ComboBoxes,ListBoxes等的新SelectedItem)
Nicolas

9

您只需要看一下名字...“属性”。这是什么意思?字典以多种方式对其进行定义,但在这种情况下,“事物的本质或独特属性或质量”最为合适。

考虑行动的目的。实际上,您是在更改还是检索“基本或独特属性”?在您的示例中,您正在使用一个函数来设置文本框的属性。看起来有点傻,不是吗?

属性实际上是函数。它们都编译为getXXX()和setXXX()。它只是将它们隐藏在语法糖中,但正是糖为过程提供了语义。

考虑诸如属性之类的属性。汽车具有许多属性。颜色,MPG,模型等。并非所有属性都可以设置,有些可以计算。

同时,方法是一种动作。GetColor应该是一个属性。GetFile()应该是一个函数。另一个经验法则是,如果它不改变对象的状态,那么它应该是一个函数。例如,CalculatePiToNthDigit(n)应该是一个函数,因为它实际上并没有改变它所附加的Math对象的状态。

这可能有点杂乱无章,但实际上归结为决定对象是什么以及它们代表什么。如果您不知道它应该是属性还是函数,那么也许无关紧要。


9

对称地,属性是对象的属性。方法是对象的行为。

标签是一个属性,使其成为属性更有意义。

在面向对象编程方面,您应该对什么是行为的一部分以及什么仅仅是属性有一个清晰的了解。

汽车{颜色,型号,品牌}

汽车具有“颜色”,“模型”和“品牌”属性,因此,没有方法SetColor或SetModel是没有意义的,因为相反地,我们不要求Car设置自己的颜色。

因此,如果将属性/方法案例映射到现实生活中的对象,或者从对称的角度来看待它,您的困惑将真正消失。



3

我更喜欢将属性用于具有1个参数的添加/设置方法。如果参数更多,请使用方法。


3

属性只能简单设置并获得一个衬里。还有更多,它实际上应该移到一种方法上。复杂的代码应始终位于方法中。


3

我仅将属性用于变量访问,即获取和设置单个变量,或获取和设置控件中的数据。一旦需要/执行任何类型的数据操作,我就会使用方法。


3

就设计而言,属性表示类对象的数据或属性,而方法则表示类对象的动作或行为。

在.Net中,世界还有其他使用属性的含义:

  • 在数据绑定中使用属性,而没有使用get_ / set_方法。
  • XML序列化用户属性是序列化的自然机制。
  • 通过PropertyGrid控件和内部ICustomTypeDescriptor可以访问属性,如果您正在编写自定义库,则可以有效地使用属性
  • 属性是由Attributes控制的,可以明智地使用它来设计面向方面的软件。

对“物业”用法的误解(IMHO):

  • 用于公开小的计算:ControlDesigner.SelectionRules的get块运行到72行中!
  • 用于公开内部数据结构:即使属性未映射到内部数据成员,也可以将其用作属性,即使它是类的属性。反之,即使不建议使用类属性的属性,也要像数据成员一样返回数组(相反,方法用于返回成员的深层副本。)

在这里的示例中,它可能被编写为,具有更多业务含义,例如:

public String Title
{
    set { Label.Text = text; }
}

2

属性非常好,因为只要可以访问,就可以在Visual Studio的视觉设计器中访问它们。

如果您只是在设置和获取,并且可能进行了一些验证而不访问大量代码,则使用它们来使用。注意,因为在验证期间创建复杂的对象并不简单。

其他任何方法都是首选方法。

这不只是关于语义。在Visual Studio视觉设计器中,使用不适当的属性会产生怪异。

例如,我在类的属性中获取配置值。该配置类实际上会打开一个文件并运行sql查询以获取该配置的值。这在我的应用程序中引起了问题,该配置文件将由Visual Studio本身而不是由我的应用程序打开和锁定,因为它不仅读取而且写入了配置值(通过setter方法)。为了解决这个问题,我只需要将其更改为一种方法即可。


1

这是有关何时使用Bill Wagner的属性与方法的一组很好的指南

  • 当所有这些都成立时,请使用Property:getter应该很简单,因此不太可能引发异常。请注意,这意味着没有网络(或数据库)访问权限。两者都可能失败,因此将引发异常。
  • 它们不应相互依赖。请注意,这将包括设置一个属性并使其影响另一个属性。(例如,设置FirstName属性将影响由名+姓氏属性组成的只读FullName属性,意味着存在这种依赖性)
  • 它们应该以任何顺序设置
  • 吸气剂没有明显的副作用。请注意,此准则并不排除属性中某些形式的惰性评估。
  • 该方法必须始终立即返回。(请注意,这排除了进行数据库访问调用,Web服务调用或其他类似操作的属性)。
  • 如果成员返回一个数组,请使用一个方法。
  • 重复调用getter(无插入代码)应返回相同的值。
  • 重复调用设置器(具有相同的值)应该与单个调用没有区别。

  • get不应返回对内部数据结构的引用(请参阅第23条)。方法可以返回深层副本,并且可以避免此问题。

*摘自我对重复问题的回答。


在这里获得最高评价和接受的答案stackoverflow.com/a/1294189/1551 为什么反对?
克里斯·巴伦斯

2
我知道我参加聚会有点晚了,但是投票失败的原因很可能是由于您复制粘贴了答案。通过复制粘贴,您承认该问题基本上是另一个问题的重复。因此,您应该将其标记为重复而不是回答它。我建议查看有关Meta的文章,了解如何处理重复的问题。
约书亚

0

这很简单。

1:在需要在存储到字段之前验证数据时使用use属性。因此,以这种方式,属性为您的字段提供了封装。因为如果您离开字段,公共最终用户可以根据您的业务需求分配任何可能有效或无效的值,例如年龄应大于18。因此在存储值之前,我们需要检查其有效性。这样,属性表示数据。

2:当需要执行某些操作(例如,提供一些数据作为参数,并且方法根据提供的值进行处理并返回处理后的值作为输出)时,请使用method。或者您想通过此计算更改某些字段的值。“以这种方式方法代表了行动”。


-1

我来自java我使用get..set ..方法已有一段时间了。

当我编写代码时,我不会自问:“访问这些数据很简单还是需要繁重的过程?” 因为事情可以改变(今天检索此属性很简单,所以明天可能需要一些或繁重的过程)。

今天我有一个方法SetAge(int age)tomonrow我也将有一个方法SetAge(date birthdate)使用出生日期来计算年龄。

我非常失望的是,get和set中的编译器转换属性,但是不认为我的Get ...和Set ..方法相同。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.