代码之家  ›  专栏  ›  技术社区  ›  Bernhard Hofmann

C可以是静态的方法应该是静态的吗?[关闭]

  •  100
  • Bernhard Hofmann  · 技术社区  · 17 年前

    C方法 可以 是静态的还是静态的?

    我们今天讨论这个问题,我有点犹豫。假设您有一个很长的方法,可以从中重构几行。新方法可能从父方法中获取一些局部变量并返回一个值。这意味着它 能够 静止不动。

    问题是: 应该 它是静态的吗?它不是静态的,不是由设计或选择决定的,只是由它的性质决定的,因为它不引用任何实例值。

    21 回复  |  直到 17 年前
        1
  •  58
  •   Scott Wisniewski    17 年前

    这要看情况而定。 实际上有两种静态方法:

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

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

    如果您有一个方法在第一个类别中(可以是静态的),并且您需要将其更改为访问类状态,那么就可以比较直接地确定是否可以将静态方法转换为实例方法。

    然而,在大型代码库中,大量的调用站点可能会进行搜索,以确定是否有可能将静态方法转换为非常昂贵的非静态方法。很多时候人们会看到电话号码,然后说“好的……我最好不要改变这个方法,而是创建一个能满足我需要的新方法”。

    这可能导致:

    1. 很多代码重复
    2. 方法参数数量的爆炸

    这两件事都不好。

    所以,我的建议是,如果您有一个超过200K的代码库,我只会使方法成为静态的,如果它们必须是静态方法的话。

    从非静态到静态的重构相对容易(只需添加一个关键字),因此,如果您希望稍后使一个可以静态到实际的静态(当您需要它在实例外部的功能时),那么您可以。但是,逆重构,将一个可以是静态的方法转换为实例方法要花费很多。

    对于大型代码库,最好是在易于扩展的方面出错,而不是在思想纯洁的方面出错。

    所以,对于大型项目来说,除非你需要,否则不要使事情静止不动。对于小项目,只要做你最喜欢的。

        2
  •  42
  •   Joel Coehoorn    14 年前

    我愿意 使它成为 公众的 的静态成员 那个班 .原因是使它成为公共静态的是对类的“类型”说了些什么:不仅“这种类型知道如何做这种行为”,而且“这是这种类型执行这种行为的责任”。很可能这种行为不再与较大的类型有任何实际的关系。

    但这并不意味着我不会让它静止不动。问问自己:新方法在逻辑上是否属于其他地方?如果你能回答“是”,你可能真的想让它静止下来(同时也要移动它)。即使这不是真的,你仍然可以使它静止。只是不要做标记 public .

    为了方便起见,你至少可以标记一下 internal . 如果您不容易访问更合适的类型,这通常可以避免移动方法,但在需要的地方仍然可以访问它,这样它就不会作为类用户的公共接口的一部分出现。

        3
  •  20
  •   Michael    17 年前

    不一定。

    将公共方法从静态方法移动到非静态方法是一个破坏性的更改,需要对所有调用方或使用者进行更改。如果一个方法看起来像一个实例方法,但碰巧没有使用任何实例成员,我建议将它作为一个实例方法,作为将来校对的度量。

        4
  •  13
  •   JP Alioto    17 年前

    对。之所以“它可以是静态的”,是因为它不会对调用它的对象的状态进行操作。因此,它不是实例方法,而是类方法。如果它可以在不访问实例数据的情况下完成所需的工作,那么它应该是静态的。

        5
  •  12
  •   Jabe    17 年前

    是的,应该的。有各种各样的 metrics of coupling 它度量类如何依赖于其他事物,如其他类、方法等。使方法保持静态是一种降低耦合度的方法,因为 当然 静态方法不引用任何成员。

        6
  •  8
  •   Indeed is Trash    17 年前

    我认为如果你把它标记为静态的,它会使它更易读一点……然后有人会知道它不引用任何实例变量,而不必读取整个函数……

        7
  •  6
  •   Tamas Czinege    17 年前

    就我个人而言,我是一个无国籍的狂热者。您的方法需要访问类的状态吗?如果答案是否定的(很可能是否定的,否则你不会考虑让它成为一个静态方法),那么是的,去做它。

    没有进入国家就不那么让人头疼了。正如隐藏其他类不需要的私有成员是一个好主意一样,隐藏状态对不需要它的成员也是一个好主意。减少访问可能意味着更少的错误。此外,它使线程处理更容易,因为保持静态成员线程安全更容易。由于运行时不需要将引用传递给 作为静态方法的参数。

    当然,缺点是,如果您发现以前的静态方法由于某种原因必须访问状态,那么您必须更改它。现在我明白了这可能是公共API的一个问题,所以如果这是公共类中的公共方法,那么也许您应该稍微考虑一下这一点的含义。尽管如此,在现实世界中,我从来没有遇到过这样的情况,事实上这导致了一个问题,但也许我只是幸运而已。

    所以,是的,一定要努力。

        8
  •  6
  •   agnieszka    17 年前

    静态方法比非静态方法更快,因此是的,如果可以,它们应该是静态的 没有什么特别的理由让他们不停地 .

        9
  •  4
  •   17 of 26    17 年前

    仅仅因为你能做到而使某个东西静止是一个不好的主意。静态方法应该是静态的,因为它们的设计,而不是偶然的。

    就像迈克尔所说的,稍后更改这个将破坏正在使用它的代码。

    尽管如此,听起来您好像是在为类创建一个私有实用程序函数,实际上,这是一个静态的设计。

        10
  •  4
  •   Chris Shaffer    17 年前

    如果您能够重构出几行代码,结果方法可能是静态的,这可能表明您从该方法中提取的代码行根本不属于包含类,您应该考虑将它们转移到自己的类中。

        11
  •  4
  •   Thomas Hansen    17 年前

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

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

    所以是的,让你的代码快速运行可能很重要,如果你让你的方法成为静态的,这可能会发生,但通常比这更重要的是让你的代码尽可能不产生错误。实现这一点的一种方法是让代码尽可能少地访问“私有内容”。

    乍一看,这似乎无关紧要,因为OP显然在谈论重构,在这种情况下,重构不会出错并创建任何新的bug,但是这个重构的代码必须在将来维护和修改,这使得您的代码在访问私有实例m时,对于新的bug具有更大的“攻击面”。余烬。所以总的来说,我认为结论是 “是的,主要是您的方法应该是静态的” 除非有任何其他原因不能使它们保持静止。这仅仅是因为它“更好地使用封装和数据隐藏,并创建‘更安全’的代码”…

        12
  •  2
  •   Prankster    17 年前

    就个人而言,我别无选择,只能让它静止不动。在这种情况下,Resharper会发出警告,我们的PM有一条规则“Resharper不会发出警告”。

        13
  •  1
  •   Scott Stanchfield    17 年前

    这取决于具体情况,但通常我不会使这些方法成为静态的。代码总是在变化,也许有一天我会把这个函数变为虚拟的,并在子类中重写它。或者有一天它需要引用实例变量。如果必须更改每个调用站点,则很难进行这些更改。

        14
  •  1
  •   Foredecker    17 年前

    我建议最好的思考方法是:如果需要一个类方法,当类的实例没有实例化时需要调用该方法,或者维护某种全局状态,那么静态是一个好主意。但总的来说,我建议您最好让成员非静态的。

        15
  •  1
  •   KdgDev    17 年前

    您应该考虑一下您的方法和类:

    • 你打算如何使用它们?
    • 您是否需要从不同级别的代码中获得大量的访问权限?
    • 这是一个方法/类吗?我可以在几乎所有可以想到的项目中使用它。

    如果最后两个是“是”,那么您的方法/类可能是静态的。

    最常用的例子可能是 Math 班级。每个主要的OO语言都有它,并且所有的方法都是静态的。因为您需要能够随时随地使用它们,而无需创建实例。

    另一个很好的例子是 Reverse() C语言中的方法。
    这是一个静态方法 Array 班级。它颠倒了数组的顺序。

    代码:

    public static void Reverse(Array array)
    

    它甚至不返回任何内容,您的数组是相反的,因为所有数组都是数组类的实例。

        16
  •  1
  •   Scott Dorman    17 年前

    只要你用新方法 私有静态 这不是一个突破性的变化。事实上,fxcop将此指南作为其规则之一。( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ,包含以下信息:

    将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点。发出非虚拟调用站点将阻止在运行时检查每个调用,以确保当前对象指针非空。这可以为性能敏感的代码带来可测量的性能增益。在某些情况下,访问当前对象实例的失败表示一个正确性问题。

    尽管如此,David Kean的第一条评论更简洁地总结了人们的担忧,他说,这实际上更多的是为了正确,而不是为了提高绩效:

    虽然这条规则被归类为性能问题,但是使方法静态化的性能改进仅为1%左右。 相反,它更像是一个正确性问题,它可以通过成员未能使用其他实例成员来指示成员中的不完整或错误。静态标记方法( 共享 在VisualBasic中)明确表示不想接触实例状态。

        17
  •  1
  •   damageboy    17 年前

    我肯定会把我能做的任何事情变成静态的,原因不同:

    当jit'd时,静态函数在没有“this”参数的情况下被调用。 这意味着,例如,一个3参数的非静态函数(成员方法) 使用堆栈上的4个参数进行推送。

    编译为静态函数的相同函数将使用3个参数进行调用。 这可以为JIT释放寄存器并节省堆栈空间…

        18
  •  1
  •   Lennaert    17 年前

    我在“只让私有方法静态化”阵营中。生成一个公共方法可以引入您不想要的耦合,并且可能会降低可测试性:您不能存根一个公共静态方法。

    如果要对使用公共静态方法的方法进行单元测试,则最终也要对静态方法进行测试,这可能不是您想要的。

        19
  •  1
  •   I. J. Kennedy ShankarSangoli    16 年前

    由于某种原因而使非静态方法成为固有的静态方法,这很烦人。才智:

    我给银行打电话要我的余额。
    他们要我的账号。
    够公平的。实例方法。

    我给我的银行打电话询问他们的邮寄地址。
    他们要我的账号。
    世界跆拳道联盟?失败应该是静态方法。

        20
  •  0
  •   user29439    16 年前

    我一般是从纯函数的函数角度来看的。它需要是实例方法吗?如果没有,您可能会受益于强制用户传递变量,而不是破坏当前实例的状态。(好吧,您仍然可以管理状态,但重点是,通过设计,不要这样做。)我通常将实例方法设计为公共成员,并尽最大努力使私有成员成为静态的。如果需要的话(之后您可以更容易地将它们提取到其他类中。

        21
  •  -1
  •   Jhonny D. Cano -Leftware-    17 年前

    在这些情况下,我倾向于将方法移动到静态库或实用程序库,因此我不会将“对象”的概念与“类”的概念混合在一起。