就记忆和时间而言,将方法设为静态更好吗?
答案 0 :(得分:85)
通常是的,没有必要传递“this”引用。该引用在ECX寄存器中传递,因此不需要额外的堆栈空间。如果您从同一类的实例方法进行调用,则已设置该寄存器,根本不会有任何节省。但是当方法在另一个类中时,它可以帮助缓解x86 CPU核心的压力,x86没有很多寄存器。看到可测量的性能改善将非常罕见。
我虔诚地将不使用实例成员的类的方法标记为静态。我重视static关键字提供的固有契约:“此方法不会改变对象状态。”
答案 1 :(得分:53)
如果方法不需要来自其所属类的任何状态信息,则应该使方法成为静态。
如果您不关心多态,可以通过决定是否接受类实例成员并将它们作为参数传递给方法,将任何方法编写为实例或静态。 你应该考虑什么,是语法是否自然,代码是否易于理解和有意义等等。
您可能不应该担心在此级别进行优化,因为实例与静态方法的性能开销可以忽略不计。是的,在调度表中使用了一些类型的空间(如果方法是虚拟的) - 但它是一个微小的,恒定的开销。是的,调用实例方法与静态方法的开销也很小 - 但同样很小。
这似乎是微观优化的一个层次,除非你有可衡量的,切实的证据,否则实际上会影响程序的性能,你应该避免。事实上,如果你做错了,传递额外参数(将它们复制到堆栈等)而不是通过你的类型的隐藏this
引用访问它们的成本可能会导致更糟< / em>表现。
您最好分析方法的语义,并在此基础上做出静态/实例决策。
答案 2 :(得分:9)
如果你打算传递实例(SomeStaticMethod(obj, "abc", 123);
),那么不是真的。你只能在没有多态的场景中有用地使用静态方法,在这种情况下,很可能无论如何都会内联任何简单之类的东西。
自然地使用对象(obj.SomeMethod("abc",123);
) - 保持代码简单,个人资料以查找性能问题 - 非常不太可能在实例和静态之间的区别,除非您运行一些非常紧密循环。 某些可能很重要的场景,但它们非常专业。
答案 3 :(得分:5)
静态方法和非虚拟实例方法之间几乎没有区别。后者只有this
prointer / reference作为“隐藏”参数。在生成的机器代码中,两种调用看起来非常相似。
如果方法不依赖于/修改对象,则该方法应该是静态的。
另一方面,虚拟方法(可覆盖)要求调用者在所谓的vtable中查找确切的实现。除了阻止编译器内联非常小的方法(经常内联简单属性访问器)之外,查找还需要几个周期。
但是,虚拟方法是CLR中C#/中可用的最快的动态调度方式。比代表和反思快得多。
答案 4 :(得分:3)
有很多这类问题。静态方法更快/更慢吗?虚拟功能更快/更慢吗? i ++比++ i更快/更慢吗?是(;;)比while(true)更快/更慢吗?
值得抓住一些软件和tuning it。在实践中,这将使您对实际影响软件性能的各种事物有一个很好的认识。
然后你会看到这样的问题的答案(大部分时间)是无关紧要的。
如果我可以概括一下,根据我的经验,使软件变慢的事情是使用看起来无辜的代码行,但其时间消耗可能比想象的大几个数量级。由于它们看起来无辜,因此通过查看代码无法可靠地找到它们。示例:重复分配,初始化和取消分配大型数据结构,以确保它们存在。国际化不需要的字符串。通知式编程,可以将属性的简单设置转换为大型数据结构中的大量方法调用。简单的O(n ^ 2)运算,除非n变大,否则永远不会成为问题。认为(a&lt; b)花费大约相同的时间长度a a和b是int还是big class。这种“看起来无辜的时间倍增”对多层抽象产生了复合效应,因此根据我的经验,大型软件往往充满了它。
答案 5 :(得分:1)
在大多数情况下,差异是可以忽略的,但静态更有效。
静态方法调用中避免了以下步骤:
答案 6 :(得分:0)
我发现我在给定类中编写的许多实用程序方法只需要类中的一些数据成员,或者根本不需要。在这些情况下,我倾向于将这些方法编写为(独立的)静态方法,直接传递他们需要的少数数据项。
如果它们对其他课程特别通用且有用,我也可以公开。