静态方法总是保存在内存中吗

本文关键字:内存 存在 保存 静态方法 | 更新日期: 2023-09-27 18:26:07

我的整个开发团队都认为,静态方法使用起来很糟糕。

在某些情况下,我真的看不出有什么缺点。当我以前需要一个无状态方法时,我总是使用静态方法。

我同意他们的一些观点,例如,我知道他们很难测试(尽管这并非不可能)。

我不明白的是,他们声称,静态方法总是保存在内存中,并将填充基本的内存使用。因此,如果您在程序中使用100个静态方法,那么当程序启动时,所有方法都会加载到内存中,并且会不必要地填充内存。此外,静态方法还会增加内存泄漏的风险。

这是真的吗?

仅仅为了调用方法就必须创建一个类的新实例,这是非常不方便的。但他们现在就是这样做的,在一个方法的中间创建一个实例并调用该方法,这可能只是一个静态方法。

静态方法总是保存在内存中吗

就内存而言,静态方法和实例方法之间没有区别。实例方法只有一个额外的参数this。其他一切都是一样的。此外,扩展方法很容易添加到C#中的基本方法,所需要的只是语法来公开隐藏的this参数。

方法为它们的机器代码(处理器执行的实际代码)占用空间。以及一个描述该方法如何存储对象的表,帮助垃圾收集器发现本地变量和CPU寄存器中的对象根。此空间取自"加载器堆",这是CLR创建的与AppDomain关联的内部数据结构。只发生一次,当方法第一次执行时,正好及时。释放该空间需要卸载该应用程序域。静态变量也在加载器堆中分配。

不要放弃静态方法的巨大优势。它们可以极大地提高代码的可读性和可维护性。由于他们的合同,他们不能改变对象的状态。因此,它们几乎没有副作用,因此很容易推理它们的作用。然而,如果它们让你添加静态变量,那么它们的作用恰恰相反,全局变量就是邪恶的。

仅仅为了调用方法就必须创建一个类的新实例,这是非常不方便的。但他们现在就是这么做的

坦率地说,他们太荒谬了。

正如评论者Groo所指出的,在本机编译级别,实例方法甚至与静态方法没有什么不同。只是有一个隐式参数被传递给实例方法,而对于静态方法,"所见即所得"。

运行时可以优化对方法的访问。在第一次执行该方法之前,它可能不会对其进行JIT编译。在实际需要IL之前,它甚至可能不会将IL从程序集中加载到内存中。但是,它可以用静态方法和实例方法同样好地执行这些优化。

事实上,强制所有方法都是实例方法比使用静态方法更糟糕,因为这意味着对于某些方法,可以任意创建一个无用的对象。虽然运行时可能能够检测到对象引用未使用,从而使其具有最短的使用寿命,但它无法避免完全分配对象,即使是退化对象也会在其活动时占用一些内存,并增加垃圾收集的成本。


除此之外,让我们暂时假设你的同事是正确的。你会得到什么?有任何可衡量的绩效差异吗?可疑的让我们面对现实吧:托管代码,尤其是C#,有可能向我们隐藏大量消耗性能的实现细节。我们使用像C#这样的托管代码语言的主要原因是,我们在生产力和代码正确性方面获得了很大的提高,这些可能的低效率是值得的。大多数时候,尤其是在现代计算机上,它们实际上是看不见的。

碰巧的是,您的同事不正确,并且将方法变成实例方法(否则可能是静态方法)在任何方面都没有好处。但即使事实并非如此,花时间编写模糊、不具表现力的代码以避免一些无法衡量、未经证实的性能成本也是一种浪费。(我知道没有人愿意比较实际的性能差异,因为如果他们这样做了,他们就不会发现通过消除所有静态方法来提高性能)。