【问题标题】:What is difference between boxing and class value type field? [duplicate]装箱和类值类型字段有什么区别? [复制]
【发布时间】:2022-01-13 20:00:15
【问题描述】:

我有点困惑,如果我创建一个类 Test 的实例,这意味着在堆栈中创建对存储字段 a 的堆的引用。

class Test
{
    public int a;
}

Test test = new Test();
test.a = 10;

我在这里创建 o,所以这意味着在堆栈中创建对存储值 10 的堆的引用。据我所知,在这两种情况下,我们在堆中都有相同的变量二进制表示。

object o = 10;

为什么在第二种情况下我会拳击但在第一种情况下没有拳击?

【问题讨论】:

  • 好吧,aint 类型,而您正在为其设置 int,所以将 int 设置为 int,那么为什么需要拳击呢?而在其他代码上,您将int 设置为object,所以有两种不同的类型。
  • 装箱意味着采用一个值类型,它存在于存储该变量的任何位置的变量中,而不是将其存储在堆上。这是在堆上为值类型分配内存并将值复制到那里的行为。在第一个示例中,您在做同样的事情,您正在为包含 int 字段的对象分配空间。但是将值存储到该字段中不需要装箱,因为 int 变量已经位于堆上。因此,您不需要为该对象中的 int 分配单独的内存。
  • 堆中的内容会有所不同,因为该类将包含其他信息,而装箱的 int 将只是 int 的值。
  • @juharr 不太确定。该框与Test本质上是一样的:一个类型句柄+字段
  • 或者您可能想通过将a 设为测试类中的对象来提供一个更有趣的示例

标签: c#


【解决方案1】:

在第二种情况下,您正在实例化一个堆变量(32、64 位长),该变量指向堆中存储实际 32 位 10 的另一个区域。

在第一种情况下,包含对象的堆区域存储整数值的完整值

【讨论】:

  • 不过还是一样的:test 包含一个对Test 对象的引用,而o 包含一个对o引用 int 的对象。堆栈/堆是implementation details。 OP想知道为什么o被装箱,而test没有,这与值类型/引用类型语义有关:值类型必须被装箱才能获得对它的引用,引用类型不要
  • @Charlieface你能帮帮我吗,如果我执行test.a=10,这意味着编译器通过测试引用搜索堆分配并在堆中更改4字节的整数字段a,但在第二个(对象o)也是对存储4字节整数的堆的引用。那么如果做同样的操作来改变或者取值,是不是说装箱拆箱就是性能等于改变,取类字段的值呢?还是因为低级实现细节导致拳击慢?
  • @YuraPazyn 您并没有什么意义(也许是误译?),但基本上,如果您将对象的 int 字段设置为 10,则您不会创建新对象,而如果您将 o 设置为 10,那么您将获得一个新对象。由于装箱,这会导致额外的分配,所以是的,如果您持续使用它会更慢。堆本身不相关:事实上test 是对对象的引用,test.a = 10 更改了该对象上的字段,而o = 10 将整个引用替换为新的盒装int
  • @Charlieface 太好了,现在我明白了!开箱呢,和get field value的性能一样吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-11
  • 2011-10-01
  • 2011-01-25
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多