代码之家  ›  专栏  ›  技术社区  ›  dlamblin

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

  •  337
  • dlamblin  · 技术社区  · 16 年前

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

    13 回复  |  直到 6 年前
        1
  •  230
  •   Community pid    7 年前

    静态方法与实例方法
    10.2.5 Static and instance members C语言规范解释了这种差异。通常,静态方法可以提供比实例方法小的性能增强,但仅在某些极端情况下(请参见 this answer 了解更多细节)。

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

    “在[将成员标记为静态]之后,编译器将向这些成员发出非虚拟调用站点,这将阻止在 确保当前对象指针为 非空。这可能会导致 性能敏感代码。在某些情况下,无法访问 当前对象实例表示一个正确性问题。”

    实用类
    你不应该把它们转移到实用程序类,除非它在你的设计中有意义。如果静态方法与特定类型相关,例如 ToRadians(double degrees) 方法与表示角度的类相关,该方法作为该类型的静态成员存在是有意义的(注意,为了演示,这是一个复杂的示例)。

        2
  •  244
  •   Jon Skeet    16 年前

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

    有时,有些方法在逻辑上作用于实例,但不碰巧使用实例的任何状态 然而 . 例如,如果您正在构建一个文件系统,并且得到了目录的概念,但是您还没有实现它,那么您可以编写一个返回文件系统对象类型的属性,并且它始终只是“文件”——但是它在逻辑上与实例相关,因此应该是一个实例方法。如果要使方法虚拟化,这也很重要——您的特定实现可能不需要状态,但派生类可能需要状态。(例如,询问集合是否为只读-您可能尚未实现该集合的只读形式,但它显然是集合本身的属性,而不是类型。)

        3
  •  49
  •   Ben    6 年前

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

    你不必把它移到另一个类中去,除非它被另一个类共享,而这个类同样紧密地联系在一起,从概念上来说。

        4
  •  21
  •   community wiki JasonTrue    16 年前

    我敢肯定在你的情况下不会发生这种情况,但是我在一些代码中看到过一种“臭味”,那就是我必须通过维护使用大量静态方法来忍受这种气味。

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

    然而,当静态方法分解出实际上不依赖于对象实例状态的域逻辑时,它们是非常有用的。它们可以使您的代码更具可读性。

    只是要确保你把它们放在正确的地方。静态方法是否会干扰其他对象的内部状态?是否可以很好地说明他们的行为属于这些类中的一个类?如果你没有正确地分开关注点,你以后可能会头疼。

        5
  •  9
  •   pajics    12 年前

    这是一本有趣的书:

    http://thecuttingledge.com/?p=57

    resharper实际上并不是建议您将方法设置为静态的。 你应该问问自己,为什么这个方法在那个类中,而不是,比如,在它的签名中出现的一个类…

    但雷斯哈珀的纪录片说: http://confluence.jetbrains.net/display/ReSharper/Member+can+be+made+static

        6
  •  8
  •   Community pid    7 年前

    只需添加到@jason true's answer ,重要的是要认识到,仅仅将“static”放在一个方法上并不能保证该方法是“pure”。对于声明它的类,它将是无状态的,但它可以很好地访问其他具有状态(应用程序配置等)的“静态”对象,这可能并不总是一件坏事,但我个人倾向于选择静态方法的原因之一是,如果它们是纯的,您可以在隔离,不用担心周围的状况。

        7
  •  6
  •   Eric Schoonover thSoft    16 年前

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

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

        8
  •  6
  •   G-Wiz RameshVel    15 年前

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

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

        9
  •  5
  •   brgerner    13 年前

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

        10
  •  3
  •   Mun    16 年前

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

        11
  •  3
  •   Austin    16 年前

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

        12
  •  2
  •   Josh    16 年前

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

        13
  •  0
  •   Joseph Morgan    8 年前

    只是我的建议:将所有共享的静态方法添加到实用程序类中可以添加

    using static className; 
    

    到您的using语句,这使得代码更容易键入和读取。例如,在我继承的一些代码中,我有大量所谓的“全局变量”。我将它们全部设置为全局类的静态属性,而不是在实例类中生成全局变量。它执行任务,如果很混乱,我可以通过名称引用属性,因为我已经引用了静态名称空间。

    我不知道这是不是好的做法。我有太多关于C 4/5的知识,还有太多要重构的遗留代码,所以我只是想让RoselynTips指导我。

    乔伊