none
拆装箱问题. RRS feed

  • 问题

  • 先来三行代码:
    int i = 100;
    object o = i;
    int j = (int)o;

    `
    问题1:在第一行代码中,int i = 100,在线程堆栈区创建Int32实例,会创建SyncBlockIndex和TypeHandle吗?据我了解,好像只有在Managed Heap上创建的引用类型对象才会有这两个创建对象时的额外开销.那么,如果没有TypeHandle的话,在调用方法时是如何操作的呢?

    问题2:在《你必须知道的.NET》一书中对装箱的宏观解释中,有一句为“装箱就是值类型数据转换为无类型的引用对象”。我不是很能理解什么是无类型的引用对象?"Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type."这句是MSDN中的解释,值类型会被包装为Object类型或其值类型所实现的接口的类型,好像并没有提及"无类型"之类的词语.

    问题3:在该书中,对拆箱的宏观解释为“而拆箱就是引用类型转换为值类型,通常伴随着从堆中复制对象实例的操作.”,而微观解释为"获取已装箱对象中来自值类型部分字段的地址.".个人感觉这两句说法好像有些矛盾.宏观解释的时候说会复制对象,而微观说只获取"部分"字段的地址.这其中的部分不知指的是哪部分?但MSDN中有个拆箱的图画着拆过箱的值类型好像就是从Managed Heap上复制了对象到堆栈区.那么,在拆箱时的操作究竟是什么样的?书中的解释"从堆中复制对象实例的操作"和"获取已装箱对象中来子值类型部分字段的地址"两句有何差异?微观的解释好像和MSDN上不太符合,或许我对这个的理解不太正确.

    问题4:SyncBlockIndex是如何控制并发的?对于它不是很了解..

    呵呵..抱歉又一连串提了这么多问题..感觉这几个问题是连贯的.
    上面的问题如果有资料希望可以提供下.
    先谢过了..呵呵...
    有人说,充满技术的生活枯燥无味.. 我笑他们不懂.因为只有技术才能充实生活.. 学习就像生活,都需要善于总结,才能发现问题,取得进步.. 生活中充满了数学算式与结构,只要我们善于观察和思考..
    2009年8月12日 5:20

答案

  • 你好!
         我谈谈我个人的看法:
         1,在托管堆上创建引用类型的实例会同时附加MethodTablePtr和SyncBlockIndex,在栈上创建值类型的实例不会创建这两个字段的!
         2,无类型是指Object而言的
         3,实际上拆箱本身并不会复制字段的

              比如这样:
              (int)o;
              就只是获取值类型部分的地址。
             
              如果这样:
              int j = (int)o;
              获取值类型部分的地址,然后把字段拷贝到栈中的j变量中,这就是他说的“通常”,注意他说的是“通常”
          4,这个字段是CLR来使用的,具体如何使用,你可以参考《.NET本质论》中的论述!

          希望这个解释对你有帮助!
             
             
             
    周雪峰
    2009年8月12日 9:18
    版主
  • 第一个不知道你再问什么  -0-

    第二个  万物皆object  没有一个实例不是object 所以  包装成object 就是取消了类型的限制   简称无类型

    第三个 msdn一般只会把你需要知道的概念告诉你 内部是怎样实现的 并不需要你关心  所以也就是宏观上说说  。 
    宏观上你看到堆中装箱的是一个 装箱版本的int
    微观上 堆里面是一个 object 的箱子 箱子里面有子值类型部分字段的地址和一些别的信息(箱子本来被设计为也可以装引用类型的) 所以只拿出来"获取已装箱对象中来子值类型部分字段的地址"    这是我的理解

    第四个
    参考

    http://cnblogs.com/fanrsh/archive/2006/08/22/483075.html
    答案破千
    2009年8月12日 5:46
    版主
  • 你好,《你必须知道的.NET》,这本书我看过,挺不错的,但是这本书不适合过细的去咬它的文字,这本书特点是帮助你宏观上理解抽象的概念。

    问题一:值类型在创建时没有SyncBlockIndex和TypeHandle,值类型调用方法时是一个装箱操作,变成了引用类型。
    jon.valett@gmail.com
    2009年8月12日 7:11
    版主

全部回复

  • 第一个不知道你再问什么  -0-

    第二个  万物皆object  没有一个实例不是object 所以  包装成object 就是取消了类型的限制   简称无类型

    第三个 msdn一般只会把你需要知道的概念告诉你 内部是怎样实现的 并不需要你关心  所以也就是宏观上说说  。 
    宏观上你看到堆中装箱的是一个 装箱版本的int
    微观上 堆里面是一个 object 的箱子 箱子里面有子值类型部分字段的地址和一些别的信息(箱子本来被设计为也可以装引用类型的) 所以只拿出来"获取已装箱对象中来子值类型部分字段的地址"    这是我的理解

    第四个
    参考

    http://cnblogs.com/fanrsh/archive/2006/08/22/483075.html
    答案破千
    2009年8月12日 5:46
    版主
  • 呵呵..感谢回答..
    第一问可能是我认识上的误区,因为我没有系统学过数据结构和运行时之类的东西..在我理解,在调用方法时不是需要TypeHandle的方法表指针吗?如果值类型没有这个东西的话,如何调用方法?
    `
    在《你必须知道的.NET》中讲到拆箱时,提及字段拷贝是在拆箱操作之后执行的,我不是很明白为什么要把字段拷贝从拆箱操作中分离出来?而且,在拆箱操作中,返回的字段的地址存储在哪里?
    `
    在拆箱时,把值类型拆成相应的可空类型时,会不会有其他额外的操作?
    `
    有没有这方面的书籍可以推荐一下?
    关于编译器,CLR,Framework的,中英文的皆可...
    非常感谢回答~
    有人说,充满技术的生活枯燥无味.. 我笑他们不懂.因为只有技术才能充实生活.. 学习就像生活,都需要善于总结,才能发现问题,取得进步.. 生活中充满了数学算式与结构,只要我们善于观察和思考..
    2009年8月12日 6:02
  • 我也是一知半解拉

    要不等这本出来?

    一本绝对值得期待的书:CLR via C#, 3rd Edition - 麒麟.NET - 博客园
    答案破千
    2009年8月12日 6:10
    版主
  • 其实我想找一本可以从底层开始讲的书...
    比如学语法,学了怎么用,从编译器到IL再去讲解,然后是运行时的问题..
    讲一些基础类库的结构..比如String类的托管和非托管的代码..
    讲讲CultrueInfo,LINQ to XXX各框架..
    现在想去学WPF..想找一本可以从WPF类库的结构开始讲的书,从一开始就从概念上理清头绪..虽然这样可能学习的时间比较长,但是学到的东西会很扎实,不会碰到棘手问题就束手无策..
    有人说,充满技术的生活枯燥无味.. 我笑他们不懂.因为只有技术才能充实生活.. 学习就像生活,都需要善于总结,才能发现问题,取得进步.. 生活中充满了数学算式与结构,只要我们善于观察和思考..
    2009年8月12日 6:17
  •  Essential C# 说是也不错

    想知道内核 第一步是反编 娃哈哈

    答案破千
    2009年8月12日 6:21
    版主
  • 你好,《你必须知道的.NET》,这本书我看过,挺不错的,但是这本书不适合过细的去咬它的文字,这本书特点是帮助你宏观上理解抽象的概念。

    问题一:值类型在创建时没有SyncBlockIndex和TypeHandle,值类型调用方法时是一个装箱操作,变成了引用类型。
    jon.valett@gmail.com
    2009年8月12日 7:11
    版主
  • 补充一下,.NET 的栈还是我们以前熟悉的栈,由操作系统控制,托管堆才是.NET的东西。
    jon.valett@gmail.com
    2009年8月12日 8:39
    版主
  • 你好!
         我谈谈我个人的看法:
         1,在托管堆上创建引用类型的实例会同时附加MethodTablePtr和SyncBlockIndex,在栈上创建值类型的实例不会创建这两个字段的!
         2,无类型是指Object而言的
         3,实际上拆箱本身并不会复制字段的

              比如这样:
              (int)o;
              就只是获取值类型部分的地址。
             
              如果这样:
              int j = (int)o;
              获取值类型部分的地址,然后把字段拷贝到栈中的j变量中,这就是他说的“通常”,注意他说的是“通常”
          4,这个字段是CLR来使用的,具体如何使用,你可以参考《.NET本质论》中的论述!

          希望这个解释对你有帮助!
             
             
             
    周雪峰
    2009年8月12日 9:18
    版主
  • 非常感谢各版主的回答...
    雪峰版主回答的第三问让我知道了为什么拆箱时没有把字段拷贝包括在其中.因为拆箱的动作是(int)o,而不是int j = (int)o,这是一个拆箱和赋值的过程,在赋值时才会复制字段.
    各版主发的书和帖子我会仔细去看的..呵呵~
    再次非常感谢~~
    有人说,充满技术的生活枯燥无味.. 我笑他们不懂.因为只有技术才能充实生活.. 学习就像生活,都需要善于总结,才能发现问题,取得进步.. 生活中充满了数学算式与结构,只要我们善于观察和思考..
    2009年8月12日 13:37
  • 不用客气啊!
    我也对底层实现比较感兴趣,以后可以多多交流啊!
    周雪峰
    2009年8月12日 14:09
    版主
  • 楼主,太客气,欢迎多来此交流!
    jon.valett@gmail.com
    2009年8月12日 16:02
    版主