C# 3.0 auto-properties — useful or not?
注意:这是我开始C时发布的。有了2014年的知识,我真的可以说,汽车属性是C语言所发生过的最好的事情之一。
我习惯于使用私有和公共字段在C中创建我的属性:
1 2 3 4 5 6 | private string title; public string Title { get { return title; } set { title = value; } } |
现在,有了.NET 3.0,我们得到了自动属性:
1 | public string Title { get; set; } |
我知道这更像是一个哲学/主观问题,但是除了为每个字段保存五行代码之外,是否有任何理由使用这些自动属性?我个人的不满是,这些财产对我隐瞒了一些东西,而我不是黑色魔法的狂热爱好者。
实际上,隐藏的私有字段甚至不会显示在调试器中,这是可以的,因为get/set函数什么也不做。但是当我想要实际实现一些getter/setter逻辑时,无论如何我都必须使用私有/公共对。
我看到了这样的好处:我保存了大量代码(一行对六行),而以后又不丧失更改getter/setter逻辑的能力,但是我同样可以这样做,只需声明一个公共字段"public string title",而不需要get;set;块,这样就可以节省更多的代码。
那么,我在这里错过了什么?为什么会有人真正想要使用自动属性?
我们在堆栈溢出中一直使用它们。
您也可能对属性与公共变量的讨论感兴趣。imho这真的是一种反应,为此目的,它是伟大的。
是的,它只保存代码。当你有很多书的时候,阅读起来容易多了。它们写起来更快,维护起来也更容易。保存代码始终是一个好目标。
您可以设置不同的作用域:
1 | public string PropertyName { get; private set; } |
以便只能在类内更改属性。这并不是一成不变的,因为您仍然可以通过反射访问私有setter。
从C_6开始,您还可以创建真正的
1 2 3 | public string PropertyName { get; } public MyClass() { this.PropertyName ="whatever"; } |
在编译时将成为:
1 2 3 4 | readonly string pName; public string PropertyName { get { return this.pName; } } public MyClass() { this.pName ="whatever"; } |
在具有大量成员的不可变类中,这可以节省大量多余的代码。
使用字段而不是属性的三大缺点是:
我个人喜欢汽车用品。保存代码行有什么问题?如果您想在getter或setter中做一些事情,那么稍后将它们转换为普通属性是没有问题的。
正如您所说,您可以使用字段,如果您想稍后向它们添加逻辑,您可以将它们转换为属性。但这可能会给反射的任何使用带来问题(可能在其他地方?).
此外,属性还允许您为getter和setter设置不同的访问级别,这是您不能对字段执行的操作。
我想它和var关键字是一样的。个人喜好问题。
来自C++的创建者Bjarne Stroustrup:
I particularly dislike classes with a lot of get and set functions. That is often an indication that it shouldn't have been a class in the first place. It's just a data structure. And if it really is a data structure, make it a data structure.
你知道吗?他是对的。在get和set中简单地包装私有字段而实际上不在get/set中做任何事情的频率有多高,这仅仅是因为它是"面向对象"的事情。这是微软解决这个问题的方法;它们基本上是可以绑定到的公共字段。
一件似乎没人提到的事情是,不幸的是,自动属性对于不可变的对象(通常是不可变的结构)没有什么用处。因为你真的应该这样做:
1 2 3 4 5 | private readonly string title; public string Title { get { return this.title; } } |
(其中字段通过传递的参数在构造函数中初始化,然后是只读的。)
因此,与简单的
我总是创建属性而不是公共字段,因为您可以在接口定义中使用属性,而不能在接口定义中使用公共字段。
自动属性和C中的其他属性一样具有黑色魔力。一旦你从编译到IL的角度来考虑它,而不是先将它扩展到一个普通的C属性,它就不再像其他语言结构那样具有黑色魔力了。
我一直使用自动属性。在C 3之前,我不能为所有的输入而烦恼,而是使用公共变量。
我唯一想做的就是能够做到:
1 | public string Name ="DefaultName"; |
必须将默认值转换为具有属性的构造函数。冗长乏味的:
我认为任何直观的、减少代码行的构造都是一个很大的优点。
这些类型的特性使Ruby这样的语言非常强大(它和动态特性,也有助于减少多余的代码)。
Ruby一直以来都是这样的:
1 2 3 | attr_accessor :my_property attr_reader :my_getter attr_writer :my_setter |
它很简单,很短,如果您想在属性体的某个位置创建一个真正的实现,它不会破坏类型的外部接口。
就这么简单。
我对他们唯一的问题是他们走得不够远。同一版本的编译器添加了自动属性,添加了部分方法。他们为什么不把这两个放在一起,我无法理解。一个简单的"partial on
在我看来,你应该总是使用自动属性而不是公共字段。也就是说,这是一个折衷方案:
从使用属性命名约定的内部字段开始。当你第一次
- 需要从装配外部进入现场,或
- 需要将逻辑附加到getter/setter
这样做:
您的客户机代码不需要更改。
不过,总有一天,您的系统会增长,您会将其分解为单独的程序集和多个解决方案。当这种情况发生时,任何暴露的字段都会再次困扰您,因为正如Jeff提到的,将公共字段更改为公共属性是一个破坏性的API更改。
这里需要注意的一点是,据我所知,这只是C 3.0端的语法糖,这意味着编译器生成的IL是相同的。我同意避免使用黑魔法,但同样的,用更少的线来画同样的东西通常是一件好事。
我使用coderush,它比自动属性快。
这样做:
1 2 3 4 5 6 | private string title; public string Title { get { return title; } set { title = value; } } |
总共需要八次击键。
对于代码片段,相同名称的自动属性总共是七次击键;)
@我不明白……你不能用自动属性来做这个吗?:
1 | public string Title { get; } |
或
1 | public string Title { get; private set; } |
这就是你所指的吗?
我对汽车属性最大的不满是它们的设计是为了节省时间,但我经常发现我必须在以后将它们扩展到全面的属性。
VS2008缺少的是一个分解的自动属性重构。
事实上,我们有一个封装字段重构,这使得我的工作方式更快地只使用公共字段。