当前位置 > 首页 > Asp.net

相同类型的每个对象大小都是一样的吗?

2009-11-30 17:34:00来源:Asp.net

  阅读: 721 评论: 20 作者: Jeffrey Zhao 发表于 2009-11-30 14:09 原文链接

快速回答:“相同(引用)类型的每个对象大小都是一样的吗?”其实个问题对于大多数情况下来说应该正确的,不过的确也有些类型受到CLR的特殊照顾,因而有那么些例外。我现在尝试使用一些简单的小实验来进行验证,当然它是不严谨的,只能算是一个简单尝试而已。

比如,我们有这么一个类型:

public class SomeClass
{
    public int Field;
}

然后编写这样的代码:

var c1 = new SomeClass();
var c2 = new SomeClass();
var c3 = new SomeClass();
var c4 = new SomeClass();
var c5 = new SomeClass();

GC.Collect(2);

unsafe
{
    fixed (int* ptr1 = &c1.Field,
        ptr2 = &c2.Field,
        ptr3 = &c3.Field,
        ptr4 = &c4.Field,
        ptr5 = &c5.Field)
    {
        Console.WriteLine("Size of c1: " + ((int)ptr2 - (int)ptr1));
        Console.WriteLine("Size of c2: " + ((int)ptr3 - (int)ptr2));
        Console.WriteLine("Size of c3: " + ((int)ptr4 - (int)ptr3));
        Console.WriteLine("Size of c4: " + ((int)ptr5 - (int)ptr4));
    }
}

运行这段代码的结果是:

Size of c1: 12
Size of c2: 12
Size of c3: 12
Size of c4: 12

当然,如果我们要得出“每个SomeClass对象大小是12字节”,那么还必须有如下两个前提

  • 在堆中分配对象时是连续的。
  • 相同类型的实例,内部字段地布局(或者说“顺序”)是相同的。

但是,有一个类型可能是个特例,那就是我们随处可见的String类型。为此,我们再写一段代码进行实验:

static void Main()
{
    var c1 = new SomeClass();
    var s10 = new String('a', 10);
    var c2 = new SomeClass();
    var s20 = new String('a', 20);
    var c3 = new SomeClass();
    var s30 = new String('a', 30);
    var c4 = new SomeClass();
    var s40 = new String('a', 40);
    var c5 = new SomeClass();

    GC.Collect(2);

    unsafe
    {
        fixed (int* ptr1 = &c1.Field,
            ptr2 = &c2.Field,
            ptr3 = &c3.Field,
            ptr4 = &c4.Field,
            ptr5 = &c5.Field)
        {
            Console.WriteLine("Size of s10: " + ((int)ptr2 - (int)ptr1 - 12));
            Console.WriteLine("Size of s20: " + ((int)ptr3 - (int)ptr2 - 12));
            Console.WriteLine("Size of s30: " + ((int)ptr4 - (int)ptr3 - 12));
            Console.WriteLine("Size of s40: " + ((int)ptr5 - (int)ptr4 - 12));
        }
    }

    DoSomething(s10, s20, s30, s40);

    Console.ReadLine();
}

private static void DoSomething(params object[] args)
{
    // nothing
}

DoSomething的作用仅仅是为了避免s10-40几个字符串直接被当作垃圾而释放掉。上面这段代码中可以得出:

Size of s10: 40
Size of s20: 60
Size of s30: 80
Size of s40: 100

这个结果似乎是说:长度为10的字符串占40字节,长度为20的字符串占60字节……以此类推,长度为n的字符串占20 + 2n个字节(这也说明CLR中的字符是使用双字节的Unicode进行存储)。

真的是这样吗?事实上这个实验中并不能严格得出“不同长度String对象大小不同”,因为,万一String类型也只是直接创建了一个字符数组呢?这样,其实每个String对象的大小还是相同的,大小不同的只是字符数组而已。那么究竟事实是怎么样的呢?这只能靠WinDBG + SOS来一探究竟了,有空我再试试看。

而现在,我也只能靠猜的。我猜String对象是在自身内部包含了一长串字符,并非引用了一个字


  • 优秀ASP.NET程序员修炼之路

    2009-7-20 23:05:00

    “为人写程序”    初级的程序员或经验不足的程序员往往只意识到自己的程序是写给计算机的,而不会在意程序其实也是写给人的,或在意得不够、不全面。   写

  • 【总结—.Net Framework集合类】

    2011-9-15 20:18:00

    写在前面: 最近在学习 .Net 的集合框架,看了许多博文,也看了书,总感觉不是很明白。心里疑惑很多,每天郁闷度日。如果学技术时感到很痛苦,有两种可能,其一是学习方法不对

  • DNNVoice Show #6

    2009-5-4 16:28:00

    So Tom and I finally recorded Show #6 of the DNNVoice Thursday evening. I didn’t get a chance to

  • CSS去除免费虚拟主机的广告心得分享

    2009-8-20 0:12:00

    摘要: 相信大多数web developer都有使用免费虚拟主机的经历吧?呵呵,无论是用来做实验、新手练手,还是一些莫名其妙的用途,你总有舍不得花钱买收费虚拟主机的时候。免费空间的作用非常大。

  • Windows SharePoint Service 工作流介绍

    2007-4-2 14:35:00

    在 WSS 3 中,我们可以使用工作流将业务流程附加到一条记录( Item ),附加后的业务流程能完全控制这条记录,包括控制记录的生命周期。例如我们能创建一个简单的工作流,将一个文档发送给一

  • Imagine Cup WW Finals Website Design Competition

    2009-4-3 1:05:00

    Imagine Cups First Worldwide Finals Website Design Competition Calling artists, dreamer

  • Circumventing the KB957543 .NET 3.5 SP1 Regression Bug

    2009-1-31 20:31:00

    A couple of days ago I hit a regression bug in .NET 3.5 SP1, in which when you have a generic class

  • ReportViewer控件无法显示(ASP.NET Ajax 客户端框架未能加载,"Sys"未定义)

    2012-10-18 17:56:00

    由于换了服务器 所以网站要重新发布。 结果发布到新的服务器上的时候reportviewer却无法显示控件 一开始是用IE游览器游览的 找不都错误所在,以为是reportviewer 的问题

  • XSLT语法 在.net中使用XSLT转换xml文档示例

    2011-7-26 9:24:00

    XSL即可扩展的样式表文件。 可以格式化xml的显示,也可以将xml转换成需要的另一种格式。 学习XSL必须熟悉XPath。XSL和XPath一样简单强大,容易学习。 1. XSL既然可以

  • 【ASP.NET】GridView如何合并脚模板

    2010-9-7 15:56:00

    因为它不像DataList中有单独的FooterTemplate模板 如: <asp:DataList id=datalist1 runat=server> <Footer