方法可以是静态的,但应该是静态的

本文关键字:静态 方法 | 更新日期: 2023-09-27 17:47:25

ReSharper喜欢指出每个ASP.NET页面上有多个可以变为静态的函数。如果我真的让它们静止,对我有帮助吗?我应该将它们设置为静态并移动到实用程序类吗?

方法可以是静态的,但应该是静态的

性能、命名空间污染等在我看来都是次要的。问问自己什么是合乎逻辑的。该方法在逻辑上是对类型的实例进行操作,还是与类型本身有关?如果是后者,则将其设为静态方法。只有当它与不在您控制范围内的类型相关时,才将其移动到实用程序类中。

有时,有些方法在逻辑上作用于实例,但却没有使用实例的任何状态。例如,如果你正在构建一个文件系统,你已经有了目录的概念,但还没有实现它,你可以写一个返回文件系统对象类型的属性,它总是"file"-但它在逻辑上与实例相关,因此应该是一个实例方法。如果您想使方法虚拟化,这一点也很重要——您的特定实现可能不需要状态,但派生类可能需要。(例如,询问集合是否为只读-您可能还没有实现该集合的只读形式,但它显然是集合本身的属性,而不是类型。)

静态方法与实例方法
C#语言规范的静态成员和实例成员解释了这一区别。通常,与实例方法相比,静态方法可以提供非常小的性能增强,但仅在一些极端的情况下(有关详细信息,请参阅此答案)。

FxCop或代码分析中的规则CA1822状态:

";在[将成员标记为静态]之后,编译器将向这些成员发出非虚拟调用站点,这将阻止在每个调用的运行时,以确保当前对象指针非null。这可以为性能敏感代码。在某些情况下,无法访问当前对象实例表示正确性问题"

实用程序类
除非在设计中有意义,否则不应该将它们移到实用程序类中。如果静态方法与特定类型相关,就像ToRadians(double degrees)方法与表示角度的类相关一样,那么该方法作为该类型的静态成员存在是有意义的(注意,出于演示目的,这是一个复杂的示例)。

在类中将方法标记为static可以明显看出它不使用任何实例成员,这有助于在浏览代码时了解。

你不一定要把它移到另一个类,除非它是由另一个同样紧密相关的类共享的,从概念上讲。

我确信在您的情况下不会发生这种情况,但我在一些代码中看到的一种"臭味"是,我不得不忍受维护使用了大量静态方法。

不幸的是,它们是假定特定应用程序状态的静态方法。(当然,每个应用程序只有一个用户!为什么不让user类在静态变量中跟踪它呢?)它们是访问全局变量的光荣方式。他们还有静态构造函数(!),这几乎总是一个坏主意。(我知道有几个合理的例外)。

然而,静态方法在考虑域逻辑时非常有用,而域逻辑实际上并不依赖于对象实例的状态。它们可以使您的代码可读性更强。

只要确保你把它们放在正确的地方。静态方法是否侵入性地操纵了其他对象的内部状态?可以证明他们的行为属于这些类中的一个吗?如果你没有正确地区分问题,你以后可能会头疼。

这很有趣:
http://thecuttingledge.com/?p=57

ReSharper实际上并没有建议您将方法设置为静态的。您应该问问自己,为什么该方法在该类中,而不是在其签名中显示的类之一。。。

但以下是ReSharper纪录片中的内容:http://confluence.jetbrains.net/display/ReSharper/Member+can+be+made+static

为了补充@Jason True的答案,重要的是要意识到,仅仅在方法上加上"static"并不能保证该方法是"pure"的。就声明它的类而言,它将是无状态的,但它很可能访问其他具有状态的"静态"对象(应用程序配置等),这可能并不总是一件坏事,但我个人倾向于尽可能喜欢静态方法的原因之一是,如果它们是纯的,你可以孤立地测试和推理它们,而不必担心周围的状态。

对于类中的复杂逻辑,我发现私有静态方法在创建隔离逻辑时很有用,其中实例输入在方法签名中明确定义,不会发生实例副作用。所有输出必须通过返回值或out/ref参数。将复杂的逻辑分解为无副作用的代码块可以提高代码的可读性和开发团队对它的信心。

另一方面,它可能会导致一个被大量实用方法污染的类别。和往常一样,逻辑命名、文档和团队编码约定的一致应用可以缓解这种情况。

在给定的场景中,您应该做最可读、最直观的事情。

性能参数不是一个好参数,除非在最极端的情况下,因为唯一实际发生的事情是一个额外的参数(this)被推送到堆栈上,例如方法。

ReSharper不检查逻辑。它只检查该方法是否使用实例成员。如果该方法是私有的,并且只由(可能只有一个)实例方法调用,那么这是一个让它成为实例方法的符号。

我希望您已经了解了静态方法和实例方法之间的区别。此外,可以有一个长答案和一个短答案。其他人已经给出了很长的答案。

我的简短回答是:是的,您可以按照ReSharper的建议将它们转换为静态方法。这样做没有害处。相反,通过使方法成为静态的,实际上是在保护方法,这样就不会不必要地将任何实例成员滑入该方法。通过这种方式,您可以实现OOP原则"最小化类和成员的可访问性";。

当ReSharper建议实例方法可以转换为静态方法时,它实际上是在告诉你,";为什么。。这个方法在这个类中,但它实际上没有使用它的任何状态"所以,它给了你思考的食物。然后,您可以意识到是否需要将该方法移动到静态实用程序类。根据SOLID原则,一个班级应该只有一个核心责任。所以,用这种方法可以更好地清理类。有时,即使在实例类中,也确实需要一些辅助方法。如果是这种情况,您可以将它们保留在#区域辅助对象中。

如果函数在多个页面上共享,您也可以将它们放在一个基本页面类中,然后让所有使用该功能的asp.net页面从中继承(函数也可以是静态的)。

使方法为静态意味着您可以从类外部调用该方法,而无需首先创建该类的实例。这在处理第三方供应商对象或附加组件时很有用。想象一下,如果在调用con.Writeline()之前必须先创建一个Console对象"con";

它有助于控制命名空间污染。

我的两便士:将所有共享静态方法添加到实用程序类中可以添加

using static className; 

到您的using语句,这使代码键入更快、阅读更容易。例如,在我继承的一些代码中,我有大量所谓的"全局变量"。我没有在作为实例类的类中生成全局变量,而是将它们全部设置为全局类的静态属性。它完成了这项工作,如果很混乱的话,我可以按名称引用属性,因为我已经引用了静态命名空间。

我不知道这是不是一个好的做法。关于C#4/5,我还有很多东西要学习,还有很多遗留代码要重构,所以我只是想让Roselyn的技巧来指导我

Joey