我试图了解C#如何管理内存。我坚持使用静态元素,我阅读了很多关于这个主题的博客和文章,但我找不到一个相当令人满意的答案。
让我们定义一个代码块来帮助找到答案。
class myClass
{
static string myStr = "String Data";
static int myInt = 12;
}
在你们分享你的答案之前,让我分享一下我对这个问题的了解。请随意同意或不同意并帮助我找到正确的答案。
让我感到困惑的是,我在互联网上发现了一些关于这个主题的答案。
混淆数字1:
程序启动时,会将所有相关程序集加载到AppDomain中。加载程序集时,将调用所有静态构造函数,包括静态字段。他们将住在那里,卸载它们的唯一方法就是卸载AppDomain。
在上面的行中,明确提到存储在AppDomain上的所有静态元素。那么为什么互联网上的每个人都说“静态”#39;元素存储在堆/堆栈上?
混淆数字2:
每个静态变量都存储在堆上,无论它是在引用类型还是值类型中声明。
如果每个静态变量都存储在堆上。那么为什么有些人说值类型静态变量存储在堆栈上?
请帮助我连接点以了解C#中静态变量的内存管理。非常感谢你宝贵的时间:)
答案 0 :(得分:56)
首先,请注意所有这些都是实现细节。运行时唯一保证的是:
几乎就是这样。其他所有内容都是一个实现细节 - 规范并不关心堆栈,堆或其他任何东西。它取决于运行时的实现,并且有效的运行时可以将所有内容放在堆栈上(如果需要的话)或堆上。并且不要忘记寄存器。
现在,让我们看看你已经设法提出的一些误解:
TypeLoadException
,最有可能是首先引用该类型的方法(不用说,这会使调试静态变得棘手)。有些人可能会感到困惑。有些人不了解合同与实际实施之间的区别。有些人根本不知道他们在谈论什么。我希望有一个简单的方法可以知道哪个是哪个,但是没有。如果有疑问,你可以转到C#/ CLR规范,但这只会告诉你合同,而不是实际的现实。
托管内存的重点在于您不应该关心这些实现细节。当然,就像任何抽象一样,它会泄漏 - 通过所有不同的层和抽象来了解事物的真实情况,直到CPU微指令,内存缓存等。但依赖没什么 - 实施可以随时改变,而且过去曾经多次发生过。
答案 1 :(得分:6)
无论何时在RAM中加载进程,我们都可以说内存是 大致分为三个区域(在该过程中):Stack,Heap, 和Static(在.NET中,实际上是Heap中的一个特殊区域 仅称为高频堆。
静态部分包含“静态”成员变量和方法。什么 究竟是静态的?那些不需要的方法和变量 要创建的类的实例被定义为静态
了解更多here。
答案 2 :(得分:2)
创建了一个类的实例,初始化了所有静态成员。
静态类的成员通常存储在堆上,值类型的成员通常存储在堆栈中。
这不是必须的,您可以阅读this博客了解更多信息。
来自C#,Eric Lippert的语言设计师之一。
博客显示,与普通知识相反,它不确定值类型是否在堆栈上,引用类型是否在堆上,但它们通常是。
它没有在规范中指定。