为什么属性执行比字段或方法执行慢?

10
CLR via CSharp第10章“属性”中,Jeff Richter写道:
属性方法可能需要很长时间才能执行;字段访问总是立即完成。使用属性的常见原因是执行线程同步,这可能会永远阻塞线程,因此,如果需要线程同步,则不应使用属性。在这种情况下,最好使用方法。此外,如果可以远程访问您的类(例如,您的类派生自System.MarshalByRefObject),则调用属性方法将非常缓慢,因此,在MarshalByRefObject场景中更喜欢使用方法而不是属性。在我看来,从MarshalByRefObject派生的类永远不应使用属性。
即使属性仅定义为返回私有字段,这也是这种情况吗?为什么在线程同步中首选方法?以及为什么在MarshalByRefObject方案中首选方法
为了澄清我的问题:
Jeff似乎在做一个全面的陈述,即属性不可取,而在这两种情况下方法更好。正如Joe White所指出的那样,属性可以有任意代码。但是方法也可以运行相同的任意代码。这就是我遇到困难的部分。使用方法在同步或编排方面是否真的比属性有优势(假设使用相同的代码),或者他只是对语言约定有问题?
3个回答

9
我认为他的观点是,由于属性可以运行任意代码,所以调用代码不应该假设它会立即完成。
如果属性只返回一个字段,那么它的方法体将被JIT编译器内联,并且与字段访问一样快。因此,属性并不会变得更慢;它们是黑盒子。如果你不知道属性的实现方式,就不能假设它会快速返回。
(话虽如此,但是创建一个慢属性将明显违反.NET Framework设计准则,特别是这个:“如果操作比字段设置慢几个数量级,则使用方法而不是属性“。)
关于他建议使用方法的想法,我无法理解。属性就是方法:属性getter是一个方法(通常命名为get_PropertyName),属性setter也是一个方法(set_PropertyName),读取属性的代码编译成调用get_PropertyName的方法调用代码。没有什么特别的东西会使属性比方法更慢。

7
Jeff的观点是,“GetBlah”方法调用向读者传达“这可能很慢”,而“Blah”属性则传达“这几乎肯定很快”。因此,如果你要让某些东西变慢,就将其设置为方法。我并不完全同意这个建议——例如,我经常创建拥有慢极少发生最坏情况但具有出色平摊性能的属性。但Jeff的建议绝对是一个很好的起点;一旦你知道自己在做什么,就可以偏离它。 - Eric Lippert

5

我认为重点在于属性访问看起来像字段访问,所以人们不会期望有什么异常。

如果你有一个可能需要很长时间的属性,你应该将其重写为方法。这不会使你的代码执行更好,但它会更清楚地表明它可能需要很长时间。

就性能而言,属性访问和方法调用没有区别。实际上,属性访问就是一个方法调用。


嗯...他明确表示“调用属性方法会非常缓慢,因此,方法优于属性”。所以这不仅仅是外表的问题...至少根据Jeff的说法是这样。 - Sonic Soul
1
调用属性会很慢,人们不希望属性变慢。调用方法同样会很慢,但人们预期某些方法会很慢。 - svick

3

方法并不比属性更快,但是我们不指望方法像属性一样快速。因此,为了明确表达可能需要一些时间(在这种情况下由于线程同步),我们更倾向于使用方法。

字段根本不需要“执行”。访问一个字段就是直接访问内存。


访问实例字段是间接访问内存,因为首先您必须在内存中定位接收器 - Eric Lippert
@Eric:是的,当然,我的意思是你正在访问内存,而不是执行代码。 - Stefan Steinegger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接