.NET中的静态类何时被加载到内存中?

7
正如标题所示,我对.NET中静态类何时加载到内存中感兴趣,特别是在C#中。 我认为它类似于Java中的this question和关于静态方法的this question,即第一次使用时加载。 此外,一旦它在内存中,它会一直保留在那里直到应用程序终止,还是当垃圾收集器来清理使用它的类时就被清理了?
我意识到静态类使用的少量内存在拥有8GB + RAM标准计算机的世界中并不是非常重要,但了解内部情况总是很有趣。
编辑:
答案让我想添加更多内容来澄清一个例子。 如果我理解正确,在下面的示例中,Contraption.SomeString将首先放入内存,然后是Contraption.AnotherString,第一次通过循环。
public static class Contraption
{
    public static string SomeString = "Some String";
    public static string AnotherString = "Another String";
}

public class Processor
{
    public void Process(List<SomeClass> items)
    {
        foreach(var item in items)
        {
            if(item.Name == Contraption.SomeString)
            {
                //do something
            }
            if(item.Name == Contraption.AnotherString)
            {
                //do something
            }
        }
    }
}
3个回答

5
关于静态字段初始化,一个重要的点是使用静态构造函数。CLR有一个类加载器组件,它加载类(元数据信息)并从内存管理器请求内存分配,因为它们在程序中被使用。元数据加载是一次性工作,在此后只需按需请求内存。
从讨论中可以理解,静态类变量在任何地方第一次使用时加载并分配内存,但使用静态构造函数可以确保它们在调用类加载器时首先初始化,这是一次性调用,可以对类中的所有静态变量进行初始化,这甚至优先于第一次使用策略,因为它是当给定程序的CLR(mscoree.dll)组件加载时发生的。
静态构造函数在任何情况下都不会在第一次之后被调用(除非程序重新启动),即使有异常,它也被广泛使用,还可以通过将静态变量设置为null来收集。

静态变量不会在编译时分配内存,而是在运行时第一次使用时分配。它们存储在堆栈或堆中? - Luminous_Dev
1
@Luminous_Dev,栈和堆分配与值类型或引用类型有关,这与静态/非静态无关。 - Mrinal Kamboj

2
我假设你指的是静态类中的字段(或非静态类中的静态字段)。它们将在第一次使用之前进行初始化。这在C#规范中有描述:
10.4.5.1 静态字段初始化
类的静态字段变量初始值设定项对应于按照它们在类声明中出现的文本顺序执行的一系列赋值。如果类中存在静态构造函数(第10.11节),则在执行该静态构造函数之前立即执行静态字段初始值设定项。否则,在第一次使用该类的静态字段之前的某个实现相关时间执行静态字段初始值设定项。
静态类成员被视为垃圾回收根,并且始终可达。
您可以通过将静态成员重置为null或其他对象来强制回收对象:
public static class Foo 
{
    public static object Bar = new object();
}

// somewhere later
Foo.Bar = null;
// the object can be collected now.

是的。我发帖后意识到,没有相应的静态成员,静态类有点毫无意义。 - ninja coder
new string("My first string here") 是什么意思? - user4003407
@PetSerAl 相关于字面字符串和字符串池还有一些额外的复杂性。使用 new string() 是为了绕过这个问题。我将其改为对象,以使其更加清晰易懂。 - MarcinJuraszek
@MarcinJuraszek,我不是在谈论字符串池。System.String没有接受其他字符串实例的构造函数。如果您想创建一个具有相同值的新字符串实例,则需要调用Copy() - user4003407

0

静态变量在应用程序域的生命周期内保持不变,在.NET中,您可以在一个应用程序中拥有多个应用程序域。虽然大多数情况下,每个应用程序只有一个应用程序域,其他应用程序域主要是为了插件沙箱而创建的。

https://msdn.microsoft.com/en-us/library/2bh4z9hs(v=vs.110).aspx


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接