68

为什么 ReSharper 在方法可以变为静态时会抱怨,但不是?

是因为只创建了一个静态方法的实例(在类型上),从而节省了性能吗?

4

8 回答 8

109

我发现该评论非常有用,因为它指出了两件重要的事情:

  1. 这让我问自己,所讨论的方法是否实际上应该是类型的一部分。由于它不使用任何实例数据,您至少应该考虑是否可以将其移动到自己的类型。它是类型的一个组成部分,还是真的是一种通用的实用方法?

  2. 如果将方法保留在特定类型上确实有意义,那么由于编译器将为静态方法发出不同的代码,因此可能会提高性能。

于 2009-04-26T05:54:34.890 回答
25

来自相同警告的 FxCop 文档(已添加重点):

“不访问实例数据或调用实例方法的成员可以标记为静态(在 Visual Basic 中为共享)。将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点。发出非虚拟调用站点将阻止在运行时对每个调用进行检查,以确保当前对象指针不为空。这可以为性能敏感的代码带来可衡量的性能提升。在某些情况下,无法访问当前对象实例表示正确性问题。

于 2009-04-26T05:26:12.070 回答
6

关于这个主题的很好的辩论(SO)。我在 if-it-can-be-made-static-make-it-static 的阵营中。我之所以相信这一点,是因为为什么会有一个不使用任何实例数据的实例方法。在这种情况下它真的是一个实例方法还是实际上是一个类方法?

于 2009-04-27T02:01:15.813 回答
5

如果该方法被声明为静态,则不需要创建类的(零)个实例来使用该方法……这样可以节省垃圾收集器从堆...

另外,你的问题,正如它所写

“ ...仅创建一个静态方法的实例(在类型上)...”

意味着对于实例方法,该方法的代码会为所创建的类的每个实例重复。那不是真的。无论您为任何类型创建多少实例,方法的代码都只会加载到内存中一次。每个实例存储在堆上的对象仅存储类型的“状态”(非静态字段和一些杂项跟踪变量)。

于 2009-04-26T05:23:34.807 回答
3

这不是抱怨,只是建议。

于 2009-04-26T05:24:01.997 回答
1

对于静态方法,您不必将“this”推送到函数的堆栈中。这是它更便宜的另一个原因。

于 2009-04-26T05:23:28.067 回答
1

对我来说,这个 ReSharper 建议的最大好处是(您可以将其设置为警告、建议或提示)。是不是它鼓励我使尽可能多的方法成为静态的。这是一件好事,因为静态方法与它所属的类没有直接依赖关系。这意味着它可以很容易地作为静态成员移动到另一个类。

ReSharper 中使用静态的另一个巧妙技巧是使用“Make Method Static”重构将一组相关方法设为静态。这会将一些依赖项移动到方法参数中。当您稍后查看这组方法时,您可能会发现它们都访问特定类型的特定对象。然后,您可以使用“Make method non-static”重构,并将该对象指定为新的this指针。这会将您的方法移动到另一个类中。

由此:

internal class ClassA
{
    public ClassB Property { get; set; }

    public int Method()
    {
        var classB = Property;
        return classB.Property1 + classB.Property2;
    }
}

internal class ClassB
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

对此:

    public static int Method(ClassB property)
    {
        var classB = property;
        return classB.Property1 + classB.Property2;
    }

对此:

internal class ClassA
{
    public ClassB Property { get; set; }
}

internal class ClassB
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }

    public int Method()
    {
        return Property1 + Property2;
    }
}
于 2009-04-27T01:54:35.503 回答
0

静态在第一次使用时被实例化,并将保留在内存中。如果它不再使用,它​​可能是一个问题。静态更难测试(moke 等......)。

于 2015-02-10T11:38:12.740 回答