Resharper喜欢指出每个asp.net页面可以变为静态的多个函数。如果我让它们静止,对我有帮助吗?我应该将它们设置为静态并将它们移动到实用程序类吗?
答案 0 :(得分:249)
在我看来,性能,命名空间污染等都是次要的。问自己什么是合乎逻辑的。该方法是在逻辑上对该类型的实例进行操作,还是与类型本身相关?如果是后者,请将其设为静态方法。如果它与不受您控制的类型相关,则只将其移动到实用程序类中。
有时会有一些逻辑上对某个实例起作用的方法,但是没有碰巧使用任何实例的状态还是。例如,如果你正在构建一个文件系统并且你已经获得了一个目录的概念,但是你还没有实现它,你可以编写一个返回文件系统对象类型的属性,它总是只是“file” - 但它在逻辑上与实例相关,因此应该是一个实例方法。如果要将方法设置为虚拟,这也很重要 - 您的特定实现可能不需要状态,但派生类可能不需要。 (例如,询问集合是否为只读集合 - 您可能尚未实现该集合的只读形式,但它显然是集合本身的属性,而不是类型。)
答案 1 :(得分:234)
静态方法与实例方法
C#语言规范的10.2.5 Static and instance members解释了差异。通常,静态方法可以提供比实例方法更小的性能增强,但仅限于极端情况(有关详细信息,请参阅this answer)。
FxCop或代码分析中的规则CA1822声明:
“在[将成员标记为静态]之后,编译器将向这些成员发出非虚拟呼叫站点,这将阻止检查 确保当前对象指针的每个调用的运行时 非空。这可以带来可衡量的性能提升 性能敏感的代码。在某些情况下,无法访问 当前对象实例表示正确性问题。“
公用事业类
除非在您的设计中有意义,否则不应将它们移动到实用程序类。如果静态方法与特定类型相关,就像ToRadians(double degrees)
方法与表示角度的类相关,那么该方法作为该类型的静态成员存在是有意义的(注意,这是一个复杂的例子,用于示范的目的)。
答案 2 :(得分:54)
在类中将方法标记为static
使得很明显它不使用任何实例成员,这有助于了解何时浏览代码。
你不一定要将它移到另一个类,除非它是由另一个与概念相关联的类共享的。
答案 3 :(得分:21)
我确信在你的情况下不会发生这种情况,但我在一些代码中看到的一个“难闻的气味”我不得不通过维护使用大量静态方法而受到影响。
不幸的是,它们是假定特定应用程序状态的静态方法。 (为什么我们每个应用程序只有一个用户!为什么不让User类在静态变量中跟踪它?)它们是访问全局变量的美化方式。他们也有静态构造函数(!),这几乎总是一个坏主意。 (我知道有几个合理的例外)。
但是,静态方法在分解出实际上并不依赖于对象实例状态的域逻辑时非常有用。它们可以使您的代码更具可读性。
请确保你把它们放在正确的位置。静态方法是否会侵入性地操纵其他对象的内部状态?可以说一个好的案例,他们的行为属于这些类之一吗?如果你没有正确地分离问题,你可能会在以后遇到麻烦。
答案 4 :(得分:9)
这是有趣的读物:
http://thecuttingledge.com/?p=57
ReSharper实际上并不建议您将方法设为静态。 你应该问问自己为什么那个方法在那个类中,而不是比如在其签名中出现的一个类...
但这是resharper documentaion所说的: http://confluence.jetbrains.net/display/ReSharper/Member+can+be+made+static
答案 5 :(得分:8)
只是要添加到@Jason True answer,重要的是要意识到只是在方法上加上'static'并不能保证该方法是'纯'的。对于声明它的类,它将是无状态的,但它可能会访问具有状态(应用程序配置等)的其他“静态”对象,这可能并不总是坏事,但其中一个原因是我个人倾向于选择静态方法,如果它们是纯粹的,你可以单独测试和推理它们,而不必担心周围的状态。
答案 6 :(得分:6)
在特定场景中,您应该做一些最具可读性和直观性的内容。
性能参数不是很好的,除非在最极端的情况下,因为实际发生的唯一事情就是将一个额外的参数(this
)推送到堆栈上,例如方法。
答案 7 :(得分:6)
对于类中的复杂逻辑,我发现私有静态方法在创建隔离逻辑时非常有用,其中实例输入在方法签名中明确定义,并且不会发生实例副作用。所有输出必须通过返回值或out / ref参数。将复杂的逻辑分解为无副作用的代码块可以提高代码的可读性和开发团队对它的信心。
另一方面,它可能会导致一个被实用方法激增污染的类。像往常一样,团队编码约定的逻辑命名,文档和一致应用可以缓解这种情况。
答案 8 :(得分:5)
ReSharper不检查逻辑。它仅检查方法是否使用实例成员。 如果该方法是私有的并且只被(可能只是一个)实例方法调用,那么这是一个让它成为实例方法的标志。
答案 9 :(得分:3)
如果函数在许多页面上共享,您也可以将它们放在基页类中,然后让所有使用该功能的asp.net页面继承它(并且函数仍然可以是静态的)。 / p>
答案 10 :(得分:3)
使方法静态意味着您可以从类外部调用该方法,而无需先创建该类的实例。在使用第三方供应商对象或加载项时,这很有用。想象一下,如果在调用con.Writeline();
之前必须首先创建一个Console对象“con”答案 11 :(得分:2)
它有助于控制命名空间污染。
答案 12 :(得分:1)
我希望您已经了解了静态方法和实例方法之间的区别。另外,答案可能很长,答案很短。其他人已经提供了长答案。
我的简短答案:是,如果Resharper建议,您可以将它们转换为静态方法。这样做没有害处。相反,通过使方法静态化,实际上是在保护方法,以免不必要地使任何实例成员都不使用该方法。这样,您可以实现OOP原则“ 最小化类和成员的可访问性”。
当ReSharper建议实例方法可以转换为静态方法时,它实际上是在告诉您:“为什么该方法位于此类中,因为它实际上并未使用其任何状态?”因此,它为您提供了深思的机会。然后,您可以意识到是否需要将该方法移至静态实用程序类。根据SOLID原则,一堂课只应承担一项核心职责。因此,您可以通过这种方式更好地清除类。有时,即使在实例类中,您也确实需要一些辅助方法。如果是这种情况,您可以将它们保留在#region帮助器中。
答案 13 :(得分:0)
只是我的tuppence:将所有共享静态方法添加到实用程序类允许您添加
using static className;
到您的using语句,这使得代码更快地输入和更容易阅读。例如,我有很多被称为"全局变量"在我继承的一些代码中。我将它们全部设置为全局类的静态属性,而不是在作为实例类的类中创建全局变量。它可以完成这项工作,如果有问题,我可以按名称引用属性,因为我已经引用了静态命名空间。
我不知道这是不是很好的做法。我有很多东西可以学习C#4/5以及如此多的遗留代码来重构我只是想让Roselyn技巧引导我。
乔伊