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

时间:2010-09-12 10:01:00

标签: c# .net class

如何判断.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吗? 我知道这是一个奇怪的问题,但我相信一个对象的每个实例都会占用内存空间..

6 个答案:

答案 0 :(得分:40)

类实例的大小由以下各项确定:

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

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

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

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

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

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

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

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

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

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

答案 1 :(得分:10)

通常,当一个类具有许多实例(非静态)字段时,它们的值越大,它就越大;类的最小内存为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

答案 2 :(得分:2)

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

Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

答案 3 :(得分:2)

您还可以查看:how-much-memory-instance-of-my-class-uses。 在调用构造函数之后,有一种简单的方法来测试对象的大小。

答案 4 :(得分:2)

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

用法很简单:

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

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

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

要计算一个物体的大小,它会使用非常难以获得的真正的黑暗魔法:)看看the code

答案 5 :(得分:0)

当一个人说班级大小时,我会认为这意味着班级有多少成员,以及班级有多复杂。

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

  1. 实例变量。
  2. 自动属性。
  3. 因此,有必要说User类比Member类占用的内存更多。