**可以*静态的C#方法应该是静态的吗?

Ber*_*ann 101 c# methods static

C#方法可以是静态的吗?

我们今天正在讨论这个问题,我有点蠢蠢欲动.想象一下,你有一个很长的方法,你可以重构几行.新方法可能从父方法中获取一些局部变量并返回一个值.这意味着它可能是静态的.

问题是:它应该是静态的吗?它不是设计或选择的静态,仅仅是因为它不引用任何实例值.

Sco*_*ski 59

这取决于.实际上有两种类型的静态方法:

  1. 因为它们可以是静态的方法
  2. 因为必须是静态的方法

在中小型代码库中,您可以互换地处理这两种方法.

如果您的方法属于第一类(可以是静态的),并且您需要将其更改为访问类状态,那么可以相对直接地确定是否可以将静态方法转换为实例方法.

然而,在大型代码库中,大量的调用站点可能会进行搜索,以查看是否可以将静态方法转换为非静态方法,而且成本太高.很多时候人们会看到呼叫的数量,并说"好吧......我最好不要改变这种方法,而是创建一个新的方法,做我需要的".

这可能会导致:

  1. 很多代码重复
  2. 方法参数数量激增

这两件事都很糟糕.

所以,我的建议是,如果你的代码库超过200K LOC,那么我只会将方法设为静态,如果它们是必须静态的方法.

从非静态到静态的重构相对容易(只需添加一个关键字),所以如果你想在以后将一个可以静态化为一个实际的静态(当你需要它在一个实例之外的功能时),那么你可以.然而,反向重构将可以静态转换为实例方法的成本要高得多.

对于大型代码库,最好是在易于扩展方面进行错误,而不是在思想纯度方面.

所以,对于大型项目,除非你需要,否则不要让事情变得静止.对于小型项目,只需做你最喜欢的事情.


Joe*_*orn 43

不会让它成为该类公共静态成员.原因是使它成为公共静态是说类的类型:不仅"这种类型知道如何做这种行为",而且"这种类型的责任是执行这种行为." 而且这种行为不再与更大的类型有任何真正的关系.

但这并不意味着我根本不会让它静止.问问自己:新方法在逻辑上属于别处吗?如果您对此回答"是",您可能确实希望将其设置为静态(并将其移动).即使这不是真的,你仍然可以使它静止.只是不要标记它public.

为方便起见,你至少可以标记它internal.如果您无法轻松访问更合适的类型,这通常可以避免需要移动方法,但仍然可以在需要的地方访问它,以便它不会显示为类的用户的公共接口的一部分.

  • 同意.我通常在这种情况下使方法"私有静态". (6认同)
  • 我也不会假设私有静态.最重要的是要问自己:这种方法在逻辑上是否适合作为此类型的一部分,或者仅仅是为了方便起见?如果是后者,它可能在其他地方更合适吗? (6认同)
  • 就像:“新方法在逻辑上是否属于其他地方” - 线索是它不依赖于本地状态,也许返回类型是它所属的地方? (2认同)

Mic*_*ael 20

不必要.

将公共方法从静态方法移动到非静态方法是一个重大变化,需要对所有调用方或消费者进行更改.如果一个方法看起来像一个实例方法,但碰巧不使用任何实例成员,我建议将它作为实例方法作为未来验证的衡量标准.


JP *_*oto 13

是."它可以是静态的"原因是它不会对调用它的对象的状态进行操作.因此,它不是实例方法,而是类方法.如果它可以在不访问实例的数据的情况下完成它需要做的事情,那么它应该是静态的.


Jab*_*abe 12

是的,它应该.有各种度量的耦合度量来衡量你的类如何依赖于其他东西,比如其他类,方法等.使方法静态是一种保持耦合程度的方法,因为你可以确定静态方法不引用任何成员.

  • 不必要.静态方法不会访问实例信息,也不会像您所说的那样访问成员,但它能够与其他类以及另一种常用方法进行交互.静态并不意味着必然会减少耦合.但是,我理解你的观点. (7认同)

Jas*_*yon 8

我认为如果你将它标记为静态会使它更具可读性......然后有人会知道它不会引用任何实例变量而不必读取整个函数...


agn*_*zka 6

静态方法比非静态方法更快,所以是的,如果可以,它们应该是静态的,并且没有特殊的理由让它们保持非静态.

  • -1:教科书过早优化.在确定一般情况下的静态与非静态时,速度肯定不是第一个标准. (22认同)
  • 我的观点是,在99%的情况下,速度是判断函数是静态还是非静态的最差的原因之一.其他帖子详细阐述了面向OO设计的重要考虑因素. (5认同)
  • 这在技术上是正确的,但不是真正的物质意义上的.static/non之间的差异很少是性能的一个因素. (3认同)
  • 同意不确定,这应该是你考虑静态与否的最后*理由. (2认同)
  • @agnieszka:一般使用实例方法而不是静态方法的特殊原因是状态.如果你给方法留下静态,在一个复杂的应用程序中,你会引入一些错误,让你撕掉你的头发.考虑修改全局状态,竞争条件,线程安全等. (2认同)

Tam*_*ege 6

就个人而言,我是无国籍的忠实粉丝.您的方法是否需要访问类的状态?如果答案是否定的(并且可能没有,否则你不会考虑将其作为静态方法),那么,是的,去吧.

无法进入国家不那么头痛.正如隐藏其他类不需要的私有成员是个好主意一样,将状态隐藏在不需要它的成员中是个好主意.减少访问可能意味着更少的错误.此外,它使线程更容易,因为更容易保持静态成员线程安全.还有一个性能考虑,因为运行时不需要引用传递给这个作为静态方法的参数.

当然,缺点是,如果您发现以前的静态方法由于某种原因必须访问该状态,那么您必须更改它.现在我明白这对于公共API来说可能是一个问题,所以如果这是公共类中的公共方法,那么也许你应该考虑一下这个问题的含义.尽管如此,我从未在现实世界中遇到过这样的问题,但实际上这可能会导致问题,但也许我很幸运.

所以是的,一定要去吧.

  • 静态方法仍然可以访问状态。它只是从传递给它的对象中获取状态。相反,实例字段不一定包含可变状态。 (2认同)

Tho*_*sen 5

我很惊讶实际上很少有人在这里提到封装。实例方法将自动访问所有私有(实例)字段、属性和方法。除了从基类继承的所有受保护的。

当您编写代码时,您应该编写它,以便尽可能少地暴露并尽可能少地访问。

所以,是的,使您的代码快速可能很重要,如果您将方法设为静态,就会发生这种情况,但通常更重要的是使您的代码尽可能地无法创建错误。实现这一目标的一种方法是让您的代码尽可能少地访问“私人内容”。

乍一看,这似乎无关紧要,因为 OP 显然在谈论在这种情况下不会出错并不会产生任何新错误的重构,但是这种重构的代码必须在将来维护并进行修改,这会使您的代码受到更大的“攻击”如果它有权访问私有实例成员,则有关新错误的表面”。所以总的来说,我认为这里的结论是“是的,大多数方法应该是静态的”,除非有任何其他原因不让它们保持静态。这仅仅是因为它“更好地使用了封装和数据隐藏并创建了‘更安全’的代码”......