6

就对象大小而言,如果公开的属性不代表状态而只是将其 getter 和 setter 调用委托给另一个实体,那么属性如何代替 Get/Set 方法影响对象大小?

例如,考虑以下类:

public class Person
{
   Address _address = new Address();

   public string AddressName
   {
      get{ return _address.Name; }
      set { _address.Name = value; }
   }

   public string GetAddressName(){ return _address.Name; }
   public void SetAddressName(string name){ _address.Name = name; }

}

public Address
{
    public string Name { get; set; }
}

我猜当创建一个新的 Person 时,CLR 在确定要分配多少内存时会考虑 AddressName 属性的潜在大小。但是,如果我公开的只是 Get/Set AddressName 方法,则不会分配额外的内存来满足 AddressName 属性。因此,为了节省内存占用,在这种情况下最好使用 Get/Set 方法。但是,这不会对 Address 类的 Name 属性产生影响,因为正在保留状态。这个假设正确吗?

4

2 回答 2

15

单个对象的大小不受属性、方法、事件等数量的影响。它会影响类型元数据的大小和 JITted 代码 - 但不影响每个对象的大小。这受实例字段的影响。

我猜当创建一个新的 Person 时,CLR 在确定要分配多少内存时会考虑 AddressName 属性的潜在大小。

不,它只查看您的字段。您有一个字段 ( _address),因此加上正常的对象开销是单个实例所需的所有内存。

于 2013-02-22T13:47:45.543 回答
6

正如 Jon 已经回答的那样,对象实例的大小由其实例字段决定。但是,让我更详细一点。

一个对象实例至少与其字段大小的总和一样大。根据字段对齐约束和 CLR(公共语言运行时)布局字段的方式,可能需要考虑一些填充字节。对于引用类型,实例有两个额外的隐藏字段:同步块索引和类型引用。两者都是本机整数。在堆上,实例的最小大小为 12 字节(不管它们实际需要多少空间)。

以下面的类为例:

class X
{
    byte value1;
    string value2;
    int value3;
    long value4;
}

在 32 位系统上, 的实例X可能需要 28 个字节:

  • 同步块索引和类型引用的 2 乘以 4 个字节,
  • 一个字节byte
  • 三个填充字节,对齐下一个字段,
  • 对象引用的四个字节string
  • 另外四个字节int
  • 和八个字节long

如您所见,getter 和 setter、方法和构造函数不会占用每个对象实例中的空间。相反,有一个单独的对象(您知道它Type)维护方法列表(getter、setter 和构造函数也是方法)并包含该类型的静态字段。您可以根据需要创建任意多个类型的对象实例,但任何给定类型实例都只会有一个Type对象。

于 2013-02-22T14:55:18.563 回答