.NET中A类(对象)的大小

如何确定.NET中的Class是大还是小? 它是根据它的属性/字段的数量,其属性/字段的数据类型来衡量的吗? 或返回类型的方法? 它的参数方法? 访问其方法的修饰符,虚方法? 谢谢..

class A { string x { get; set; } } class B { int x { get; set; } } 

在这个例子中,如果我像这样实例化A类和B类

  A objA = new A(); B objB = new B(); 

类objA是更大的一个,因为它拥有一个String属性而objB只保存一个Int? 虽然我没有为它的财产设定任何价值。 谢谢

编辑:只是为了澄清我的问题

假设我有一堂课

 public class Member { public string MainEmpId { get; set; } public string EmpId { get; set; } } 

和另一堂课

 public class User { public string AccessLevel { get; set; } public string DateActivated { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Mi { get; set; } public string Password { get; set; } public string UserId { get; set; } public string UserName { get; set; } public string Active { get; set; } public string ProviderName { get; set; } public string ContactPerson { get; set; } public string Relation { get; set; } public string Landline { get; set; } public string MobileNo { get; set; } public string Complaint { get; set; } public string Remarks { get; set; } public string Reason { get; set; } public string RoomType { get; set; } } 

如果我像这样实例化它

  Member A = new Member(); User B = new User() 

对象A是否大于对象B? 我知道这是一个奇怪的问题,但我相信一个对象的每个实例都会占用内存空间。

类实例的大小由以下因素确定:

  • 实际存储在实例中的数据量
  • 值之间需要填充
  • 内存管理使用的一些额外内部数据

因此,通常需要包含字符串属性的类(在32位系统上):

  • 内部数据为8个字节
  • 字符串引用的4个字节
  • 4个字节的未使用空间(达到内存管理器可以处理的最小16个字节)

通常,包含整数属性的类需要:

  • 内部数据为8个字节
  • 整数值为4个字节
  • 4个字节的未使用空间(达到内存管理器可以处理的最小16个字节)

如您所见,字符串和整数属性占用了类中的相同空间,因此在第一个示例中,它们将使用相同数量的内存。

string属性的值当然是另一回事,因为它可能指向堆上的字符串对象,但这是一个单独的对象,而不是指向它的类的一部分。

对于更复杂的类,填充起作用。 例如,包含布尔值和字符串属性的类将使用:

  • 内部数据为8个字节
  • 布尔值为1个字节
  • 3个字节的填充以获得均匀的4字节边界
  • 字符串引用的4个字节

请注意,这些是类的内存布局示例。 确切的布局取决于框架的版本,CLR的实现,以及它是32位还是64位应用程序。 由于程序可以在32位或64位系统上运行,因此编译器甚至不知道内存布局,而是在执行之前代码是JIT:ed时决定。

通常,当一个类具有许多实例(非静态)字段时,无论其值如何,它都会更大; 类的最小内存为12个字节,引用类型的字段在32位系统上为4个字节,在64位系统上为8个字节。 其他字段可以用填充到字边界来布局,使得具有四个byte字段的类实际上可以占用存储器中的四个4字节。 但这一切都取决于运行时。

不要忘记可能隐藏的字段,例如,您的自动属性声明。 由于它们在内部由字段支持,因此它们将增加类的大小:

 public string MyProperty { get; set; } 

请注意,以下属性对类大小没有影响,因为它不受字段支持:

 public bool IsValid { get { return true; } } 

要了解类或结构实例的内存大小:在类上应用[StructLayout(LayoutKind.Sequential)]属性,并在类型或实例上调用Marshal.SizeOf()

 [StructLayout(LayoutKind.Sequential)] public class MyClass { public int myField0; public int myField1; } int sizeInBytes = Marshal.SizeOf(typeof(MyClass)); 

但是,因为运行时可以按照自己的意愿在内存中布局类,所以实例使用的实际内存可能会有所不同,除非您应用StructLayoutAttribute

虽然以下文章是旧的(.NET 1.1),但这些概念清楚地解释了CLR为应用程序中实例化的对象分配内存的行为; 他们放置了哪些堆,他们的对象引用指针正在寻址,等等。

深入了解.NET Framework内部,了解CLR如何创建运行时对象

您还可以检查: 我的类使用的内存实例有多少 。 调用构造函数后,有一种简单的方法来测试对象的大小。

github上有一个名为dotnetex的项目,它使用一些魔法并显示类或对象的大小。

用法很简单:

 GCex.SizeOf(); // size of the type GCEx.SizeOf(someObject); // size of the object; 

引擎盖下它使用了一些魔法。
要计算类型的大小,它会将方法表的指针强制转换为内部MethodTableInfo结构,并使用它的Size属性,如下所示:

 public static unsafe Int32 SizeOf() { return ((MethodTableInfo *)(typeof(T).TypeHandle.Value.ToPointer()))->Size; } 

要计算一个对象的大小,它使用真正的黑暗魔法很难得到:)看看代码 。

当一个人说出class级规模时 ,我会认为这意味着class级有多少成员,class级有多复杂。

但是,您的问题是我们创建类实例时所需的内存大小。 我们不能确定确切的大小,因为.Net框架保留并保持底层内存管理远离我们(这是一件好事)。 即使我们现在拥有正确的尺寸,价值也可能永远正确。 无论如何,我们可以确定以下内容将在内存中占用一些空间:

  1. 实例变量。
  2. 自动财产。

因此,有意义的是, User类将占用比Member类更多的内存。