我想知道在实例化类时C#类的实际代码是否会被加载到RAM中?
因此,例如,如果我有2个类CLASS A,CLASS B,其中A类有10000行代码,但只有1个字段,一个int。 B类有10行代码,1个字段也有int。如果我实例化A类,由于它的代码行,它会占用比B类更多的RAM吗?
一个补充问题,如果代码行与类一起加载到内存中,它们是否会为类的每个实例加载?或者只为所有实例一次?
提前致谢。
答案 0 :(得分:9)
在桌面框架中,我认为方法是逐个方法进行JIT的。我不知道在第一次加载类时,类的IL是否完全加载到RAM中,或者它们是否只是内存映射到汇编文件。
无论哪种方式,您都可以获得所有实例的单个副本 - 至少对于非泛型类型。对于泛型类型(和方法),它稍微复杂一些 - 所有引用类型类型参数有一个JIT表示,而每个值类型类型参数有一个JIT表示。因此List<string>
和List<Stream>
共享原生代码,但List<int>
和List<Guid>
却没有。 (适用于具有多个泛型类型参数的类型的外推。)但是,对于同一构造类型的所有实例,您仍然只获得一个副本 - 对象没有自己的本机代码副本。
答案 1 :(得分:4)
类型A的实例将占用与类型B完全相同的内存量。类型实例使用的内存量是它包含的字段的直接结果,因此如果两个类型包含相同的字段,那么这两种类型的实例将包含相同数量的内存。当然,如果你有可变长度的字段,如字符串,数组,集合等,那么你必须考虑到这一点,但如果字段设置为每种类型的相同值,那么将使用相同数量的内存
在app域中,包含每种类型方法指令的代码只会加载一次,而不是每种类型的实例。正如Jon所说,重要的是要记住每个封闭的泛型类型(所有类型参数都已声明)是一个单独的运行时类型。
顺便提一下,您的类型包含多少行源代码并不重要,但此源代码编译的IL数量是多少。但是,如果一种类型有10行源代码而另一种类型有10,000行,那么后一类的IL很可能会大得多。您可以使用.NET Reflector等工具检查IL。
答案 2 :(得分:1)
这是一篇很好的文章,描述了IL代码被JIT和加载的方式和位置: http://msdn.microsoft.com/en-us/magazine/cc163791.aspx