为什么我们使用.NET属性而不是普通的旧get / set函数?

时间:2009-06-19 19:06:55

标签: .net oop properties

我理解提供接口以间接访问类成员的许多好处。我的问题是:并不是你已经可以用任何OO语言完成的事情(使用的东西)

public int NormalClass::getQuality() {
    return this->quality;
}

protected void NormalClass::setQuality(int q) {
    this->quality = q;
}

除了纯粹的美学外,.NET属性还提供了哪些额外的好处?

如果你能为它做出令人信服的论证,我会接受“可读性”;但就个人而言,我倾向于认为get / set函数比属性更具可读性,因为它明确地是函数而不是直接值。

编辑:感谢大家的回答!这对我来说真的很有用;总结一下我从所有人那里收集/学到的东西,以下是我到目前为止得出的一些结论:

  • 物业的最大好处 来自于具体的特征 属性本身,而是 从框架和IDE功能 以特殊方式处理财产; 例如,属性编辑器,XML 序列化,数据绑定。
  • 可以将属性视为简单 某些方便的价值观 get / set函数不能:in 特别是,obj.Prop ++和obj.Prop = 值。
  • 属性让你逃脱 使用快速和脏代码 没有经过的公众成员 实施一堆的头痛 稍后获取/设置功能;如果你 应该需要添加一些逻辑 和/或使公共成员私密, 你可以简单介绍一个属性 并且不会冒任何旧代码的风险。

现在,到目前为止,有两点已经在2或3个答案中提出,我个人觉得有点可疑:这些属性意味着廉价的读/写操作,因此可以与简单变量基本相同的方式使用。我关于这一点的问题是,实际上强制执行此操作的属性中没有固有的东西;它只是如何假设被使用。对我来说,这类似于“shouldBePrivate”限定符,表示值应该只能由它自己的类直接访问,但仍然可以从外部访问;或者在街道巡逻的警察部队提醒我们,我们应该表现自己,但在我们开始犯罪时实际上并没有干涉(如果没有强制执行,它对我们真正做了什么? )。

如果属性具有某种内置机制来确保读/写便宜,我会对这一点印象更深。

15 个答案:

答案 0 :(得分:24)

Jon Skeet对他的关于why properties matter的C#文章博客有一个很好的概述。在其中,他解释了为什么应该使用属性来暴露公共领域。

至于为何使用属性而不是getter / setter方法,我建议以下想法:

  • 属性提供了更简洁,更简洁的语法,易于理解和阅读。
  • 属性启用赋值表达式链接:A.x = B.y = C.z
  • 属性清晰一致地传达数据访问的语义 - 消费者期望没有副作用。
  • .NET中的许多库都可识别属性,例如XML序列化,WPF绑定,ASP.NET双向绑定等任务。
  • 属性由IDE和许多可视化设计人员识别,可以在属性编辑器中显示。
  • 属性启用对增量(++)和减量( - )运算符的支持。
  • 可以轻松区分属性与使用反射的方法,并允许动态消费者提取有关对象公开的数据的知识。
  • C#3支持自动属性,有助于消除样板代码。

答案 1 :(得分:13)

属性(特别是.net 3.5中的自动属性)比setter / getter更简洁,代码行数减少= =维护代码少= =更少错误。

我会先说可读性,但你已经说过不会算你......:)

答案 2 :(得分:10)

我认为XML Serialization只读取/写入公共属性,因此将忽略get和set方法。

此外,如果您有一个通用的对象列表,您可以将其分配给DataGridView.DataSource,您将获得每个属性的列。这可能是@LPalmer所指的。

答案 3 :(得分:7)

不仅在语言中而且在clr中具有属性意味着.NET上的每个人都可以依赖于他们的元数据。属性具有无副作用的内涵,并且get和set都是快速操作。许多工具使用这些假设:winforms设计器,LINQ to SQL ......

因此,它不仅仅是为了方便,而且还有一个额外的元数据。

以下是其他典型假设:

customer.Name = "a";
Assert.IsTrue(customer.Name == "a");

try { var ignored = customer.Name; }
catch { Assert.Fail("Exceptions are not expected"); }

答案 4 :(得分:4)

属性的两大优势:

  • 可以在Property Grid中显示和编辑它们。没有属性,您如何知道显示编辑器的方法?
  • 他们提供了一些提示,即读取和写入都很便宜,并且读取它不会产生任何副作用。 (当然,有可能违反这一点,但是通过制作某个属性,您宣称这是您的意图。)因此,调试器可以采用该提示。如果将鼠标悬停在属性上,调试器将在工具提示中显示其值。对任何可能的方法做同样的事情是没有意义的;很容易意外地做副作用。

答案 5 :(得分:4)

查看面向对象编程的一种流行方法是根据我们头脑中的概念对程序中的类进行建模。

我们头脑中的概念是基于我们周围感知的实际物体(无论我们是否感知它们,或者我们与感知它们的其他人交流)。

我们周围的物品 - 家具,动物,航天飞机等 - 具有特定的属性并以特定的方式行动。

这就是我们获得属性和方法的地方。

在C#中,属性可能无法简化为单个字段获取或字段集(例如,它可能需要额外检查或可能涉及缓存或任何原因)。所以我们需要一个单独的属性概念,使用get-methods和set-methods来使我们的程序更接近我们希望它们建模的概念。

答案 6 :(得分:3)

本质上的属性获取/设置方法对。

属性是一种运行时支持的方法,用于公开一对具有元数据支持的get set方法,这意味着它们可以使用反射发现,而无需根据方法名称和签名猜测应该构成访问器的方法。

属性的另一个优点是它们在语法上就像字段一样,而不像方法,它具有创建更干净代码的优势。

  

我倾向于认为得到/设定   函数比a更具可读性   财产,因为它是明确的   功能而不是直接   值。

大多数时间属性都是由Jit引擎内联的,因为它们非常简单,这意味着大多数时候属性的作用就像字段一样,而不像函数那样,因此它们更接近字段的行为而不是函数。 / p>

在属性的情况下,如果函数调用和字段访问之间存在歧义,则它不会生成因为最大的部分,您不支付函数调用成本,属性getter和setter,因为它们的简单性,内联的高候选者,这意味着成本方面更接近于字段而不是函数调用*。

  • 注意:并非所有属性都很便宜,但一般指导原则指出它们应尽可能简单轻便。

答案 7 :(得分:3)

除了使用描述对象的属性的值的属性的语义正确性之外,你不能争论这个:

obj.SetValue(obj.GetValue() + 1);

VS

obj.Value++;

答案 8 :(得分:2)

对我来说,这很容易:

myprop = myvalue;
console.writeline(myprop);

不需要

mysetfunc(myvalue);
console.writeline(mygetprop);

比2更容易记住1件事

答案 9 :(得分:2)

我知道在某些情况下,您可以将属性用作数据集中的“列”名称。我认为.NET通过内省来做到这一点。我不相信这可以通过get / set函数来实现。

答案 10 :(得分:2)

也许是一个小问题,但是对于getter / setter我觉得很烦人,当我在带有'intellisense'的IDE中骑自行车时,会有一大块'getter'彼此相邻而另一块'setter' ”。我发现找到我正在寻找的东西更加困难。

答案 11 :(得分:2)

使用getset方法,您必须从一开始就决定使用它们,并且几乎总是为您的类公开的每个公共属性编写大量的样板代码。

class Point
{
    private int x, y;

    // Ew, pointless boilerplate!
    public int  getX()      { return x;   }
    public void setX(int x) { this.x = x; }

    public int  getY()      { return y;   }
    public void setY(int y) { this.y = y; }
}

// ...

Point p = new Point();
p.setX(5);
p.setY(10);

使用属性,您可以消除样板的getter和setter,用于90%只有微不足道的getter和setter的属性。您可以直接公开变量

class Point
{
    public int x, y;
}

Point p = new Point();
p.x = 5;
p.y = 10;

然后,如果您决定要向公共变量添加一些行为,则可以使用getset方法将其切换为具有实际行为的属性。这方面的好处是你班级的用户根本不会受到影响。什么都没有改变;他们无需从point.x = 5切换到point.setX(5)。您的公共接口是稳定的,允许您首先使用普通变量,然后在添加一些保护/记录/任何内容时切换到较慢的get / set方法。

class Point
{
    public int x { get; set; }
}

// No change! 
Point p = new Point();
p.x = 5;
p.y = 10;

(现在严格来说,你的语法接口没有改变,但你的类的编译接口已经改变了,所以你必须重新编译使用你的类的所有代码,如果你从变量切换到属性。你不能得到如果您的类是广泛使用的库的一部分,那么只需重新编译您的类并放弃它来代替旧类,您的库的用户将不得不针对您的库的新版本重新编译它们的代码。)

答案 12 :(得分:1)

正如usr所述:

  

“属性具有get的含义   没有副作用,两者兼而有之   得到并设置为快速操作。“

完全。暗示吸气剂/定位剂会很快。通过将某些东西暴露为属性,您暗示您正在快速获取/将属性放在对象上。方法是做某种形式的工作,假设涉及更多周期,而不仅仅是获取/设置属性。我们通常会将一个冗长的操作'属性'放入GetFoo(...)/ SetFoo(...)方法中,以指示计算操作比属性重。

答案 13 :(得分:0)

至少 DataBinding
没有它,UI相关的开发变得更加复杂。

答案 14 :(得分:0)

它们允许该类型的用户具有简化的语法,并允许您创建只读和只写字段。 从而 me.SetAge(34); age = me.GetAge(); 变 me.age = 34; age = me.age;