我的问题与静态方法与实例方法的性能特征及其可伸缩性有关。假设对于这种情况,所有类定义都在单个程序集中,并且需要多个离散指针类型。
考虑:
public sealed class InstanceClass
{
public int DoOperation1(string input)
{
// Some operation.
}
public int DoOperation2(string input)
{
// Some operation.
}
// … more instance methods.
}
public static class StaticClass
{
public static int DoOperation1(string input)
{
// Some operation.
}
public static int DoOperation2(string input)
{
// Some operation.
}
// … more static methods.
}
上面的类代表了一个辅助样式模式。
在实例类中,解析实例方法需要一些时间来做与 StaticClass 相反。
我的问题是:
this.DoOperation2("abc")
从内部 DoOperation1
同一个实例。 最佳答案
理论上,静态方法的性能应该比实例方法稍好一些,所有其他条件都相同,因为额外的隐藏 this
参数。
在实践中,这几乎没有什么区别,以至于它会隐藏在各种编译器决策的噪音中。 (因此,两个人可以“证明”一个比另一个更好的结果不一致)。尤其是自从 this
通常在寄存器中传递,并且通常在该寄存器中开始。
最后一点意味着,从理论上讲,我们应该期待一个静态方法,它接受一个对象作为参数并用它做一些事情,比作为同一对象上的实例的等效方法稍差。尽管如此,差异是如此微小,以至于如果您试图衡量它,您最终可能会衡量其他一些编译器决策。 (特别是因为该引用始终在寄存器中的可能性也很高)。
真正的性能差异将归结为您是否在内存中人为地让对象做一些自然应该是静态的事情,或者您是否正在以复杂的方式纠缠对象传递链来做自然应该是实例的事情。
因此对于数字 1。当保持状态不是问题时,最好是静态的,因为这就是 的静态.这不是一个性能问题,尽管有一个很好地使用编译器优化的总体规则 - 更有可能有人去优化正常使用的情况而不是那些奇怪使用的情况。
第 2 点。没有区别。每个成员都有一定数量的每个类成本,它包括有多少元数据、实际 DLL 或 EXE 文件中有多少代码,以及有多少 jitted 代码。无论是实例还是静态都是一样的。
与项目 3, this
为 this
确实。不过请注意:
this
参数在特定寄存器中传递。在同一个类中调用实例方法时,它很可能已经在该寄存器中(除非它被隐藏并且由于某种原因使用了该寄存器),因此不需要设置 this
的任何操作。它需要设置为什么。这在一定程度上适用于例如方法的前两个参数是调用的前两个参数。 this
不为空,这在某些情况下可用于优化调用。 this
不为空,这可能会使内联方法调用再次变得更有效率,因为为伪造方法调用而生成的代码可以省略一些它可能需要的空检查。 值得注意的是,作用于对象的通用静态方法,而不是实例方法,可以降低 http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/ 中讨论的一些成本。在没有为给定类型调用给定静态的情况下。正如他所说:“顺便说一句,事实证明,扩展方法是使泛型抽象更具性价比的好方法。”
但是,请注意,这仅与方法使用的其他类型的实例化有关,否则不存在。因此,它确实不适用于很多情况(其他一些实例方法使用了该类型,其他地方的一些其他代码使用了该类型)。
总结:
编辑:关于空检查有多便宜的注释(我在上面声称)。 .NET 中的大多数空检查根本不检查空值,而是继续他们将要做的事情,假设它会起作用,如果发生访问异常,它会变成
NullReferenceException
.因此,主要是当 C# 代码在概念上涉及空检查时,因为它正在访问实例成员,如果它成功,成本实际上为零。一个异常(exception)是一些内联调用,(因为他们想要表现得好像他们调用了一个实例成员)并且他们只是点击了一个字段来触发相同的行为,所以他们也非常便宜,而且他们仍然经常被排除在外(例如,如果该方法的第一步涉及按原样访问字段)。
关于c# - 静态方法与实例方法的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12279438/