为什么 ReSharper 在方法可以变为静态时会抱怨,但不是?
是因为只创建了一个静态方法的实例(在类型上),从而节省了性能吗?
我发现该评论非常有用,因为它指出了两件重要的事情:
这让我问自己,所讨论的方法是否实际上应该是类型的一部分。由于它不使用任何实例数据,您至少应该考虑是否可以将其移动到自己的类型。它是类型的一个组成部分,还是真的是一种通用的实用方法?
如果将方法保留在特定类型上确实有意义,那么由于编译器将为静态方法发出不同的代码,因此可能会提高性能。
来自相同警告的 FxCop 文档(已添加重点):
“不访问实例数据或调用实例方法的成员可以标记为静态(在 Visual Basic 中为共享)。将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点。发出非虚拟调用站点将阻止在运行时对每个调用进行检查,以确保当前对象指针不为空。这可以为性能敏感的代码带来可衡量的性能提升。在某些情况下,无法访问当前对象实例表示正确性问题。 ”
关于这个主题的很好的辩论(SO)。我在 if-it-can-be-made-static-make-it-static 的阵营中。我之所以相信这一点,是因为为什么会有一个不使用任何实例数据的实例方法。在这种情况下它真的是一个实例方法还是实际上是一个类方法?
如果该方法被声明为静态,则不需要创建类的(零)个实例来使用该方法……这样可以节省垃圾收集器从堆...
另外,你的问题,正如它所写
“ ...仅创建一个静态方法的实例(在类型上)...”
意味着对于实例方法,该方法的代码会为所创建的类的每个实例重复。那不是真的。无论您为任何类型创建多少实例,方法的代码都只会加载到内存中一次。每个实例存储在堆上的对象仅存储类型的“状态”(非静态字段和一些杂项跟踪变量)。
这不是抱怨,只是建议。
对于静态方法,您不必将“this”推送到函数的堆栈中。这是它更便宜的另一个原因。
对我来说,这个 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;
}
}
静态在第一次使用时被实例化,并将保留在内存中。如果它不再使用,它可能是一个问题。静态更难测试(moke 等......)。