【问题标题】:C# class size calculationC#类大小计算
【发布时间】:2009-08-24 23:18:57
【问题描述】:

在 C# (.NET) 中,方法(虚拟、静态、非虚拟)究竟如何影响类大小?

【问题讨论】:

  • 你是指程序集中的编译类,包含该类的源代码文件还是该类在内存中实例的大小?
  • 我的意思是实例的大小。 sizeof() 变量不能用于计算大小(编译器错误):“MyClass”没有预定义的大小,因此 sizeof 只能在不安全的上下文中使用(考虑使用 System.Runtime.InteropServices.Marshal.SizeOf) Marshal .SizeOf() 给出相同的错误,但在运行时。如果将 StructLayoutAttribute 应用于类声明,sizeof() 返回 1。

标签: c# .net architecture


【解决方案1】:

每个方法都占用内存来保存其字节码。每个方法的代码存在一次¹,而不是每个实例存在一次。

添加和删除实例方法(虚拟或非虚拟)不会改变分配对象的大小。这与 C++ 不同,在 C++ 中添加虚拟方法有时确实会增加分配对象的大小。与 C++ 一样,静态方法不会改变分配对象的大小。

¹ 对于泛型方法,每个实例化的类型都存在一个副本。

编辑:为了回应 cmets,我将更详细地介绍。

@Richard:这可能是真的,也可能不是(可能会有所不同)。只需要一份 IL 字节码。开放构造方法和封闭构造方法需要一个方法描述符块,以及仍包含泛型类型参数的构造实例的描述符(在泛型类型定义的泛型参数化基类型中具有泛型参数的方法)。通常,将为每个封闭构造的实例保留一份本机代码副本,该实例是一个值类型,加上一个用于零个或多个引用类型,但可能有零个(不是 JIT'd/只是解释)或两个或更多(基线和优化编译器,其中一个或多个调用堆栈没有离开基线版本,因为该方法是使用优化 JIT 重新编译的)。 再次编辑:您是正确的,因为通用参数约束只允许其实例化的所有引用类型的本机代码副本。

【讨论】:

  • 谢谢,这就是我要找的。你能提供任何官方参考吗?
  • 对于具有单个类型参数的泛型方法,泛型类型被实例化的每个值类型存在一个副本,并且所有引用类型一起存在一个副本(或零,如果没有在任何引用类型上实例化)。为多个类型参数的每个组合展开...
【解决方案2】:

每个实例的大小取决于类的字段,而不是方法。根据实现细节,实现一个接口可能会占用实例中的空间(可能每个接口一个指针大小的槽),但不能保证这样做。

但是,您将很难为实现定义的行为找到“官方参考”,因为它可能会在未来发生变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 2019-05-13
    • 1970-01-01
    • 2011-09-07
    • 2011-10-10
    • 1970-01-01
    相关资源
    最近更新 更多