是引用类型字段的时候是值类型装箱吗?

问题描述 投票:0回答:6

有代码:

struct A
{
   int b;
}

class B
{
  A a;
  int b;
}

问题是:

  1. B 中的 a 是否已装箱?
  2. B中的a是位于栈中还是堆中?
  3. A 中的 b 是否已装箱?
  4. b 是在栈中还是在堆中?
  5. B 中的 b 是否已装箱?
  6. b是在B栈中还是在堆中?

我真的不明白:(

c# .net value-type boxing
6个回答
8
投票

1)不,这里没有拳击。

2)

a
将位于堆上,尽管这是一个实现细节

3)不,

b
中的
A
未装箱

4)

b
中的
A
将存在于包含
A
的地方(因此对于
A
类型的局部变量,它通常位于堆栈上;对于像
B这样的类的实例变量
或任何静态变量,它将位于堆上);再说一次,这是一个实现细节

5)

b
中的
B
也没有装箱

6)

b
中的
B
将位于堆上 - 再次是实现细节

这里没有进行装箱,因为您没有展示任何尝试使用值类型值作为引用类型值的内容(例如

object
或接口)。

再次强调,整个堆栈/堆的区别是一个实现细节。您应该阅读 Eric Lippert 的关于该主题的博客文章


2
投票

使用谷歌我发现这个

装箱和拆箱是 C# 类型系统中的一个基本概念。通过装箱和拆箱,可以通过允许将值类型的任何值转换为和来在值类型和引用类型之间进行链接 来自类型对象。装箱和拆箱可以实现类型系统的统一视图,其中任何值 类型最终可以被视为对象。 将值类型转换为引用类型称为装箱。拆箱是一个显式操作

装箱正在将值类型转换为引用,这不在您的代码中。所以你的“b-boxed”问题的答案是“否”。


1
投票
  1. B中的a成员没有被装箱。
  2. B中的a成员位于堆上。它是对象的一部分,对象总是在堆上分配。
  3. A 中的 b 成员未被装箱(但 A 值可能被装箱)。
  4. A 中的 b 成员是 A 的一部分,因此它存储在 A 值存储的任何位置,可以在堆栈上,也可以在堆上。
  5. B中的b成员没有被装箱。
  6. B 中的 b 成员位于堆上,作为对象的一部分。

0
投票

通过引用传递值类型也不是装箱。

void SomeFunction(ref int a)
a 没有装箱。

int? value
可空值类型也不装箱。

object my_box = my_integer
my_value 是 my_integer 的盒装版本

类中包含的值类型未装箱(如果是这种情况,什么时候它会是值类型?)


0
投票

结构类型的存储位置(变量、参数或字段)在保存该类型的所有字段(公共和私有)。如果存储位置作为自动变量或参数保存在堆栈上,则其所有字段都将是类似的。如果存储位置存在于堆对象内,则其字段将位于同一个堆对象中。

装箱在内部通过为每个值类型定义一个具有相同名称和成员的类类型来工作。当将值类型值赋予需要类类型的代码时,系统会生成同名类类型的新实例,并将所有字段(公共和私有)从值类型值复制到新对象实例。尽管 C# 规范将装箱实例描述为值类型,但其行为和内部工作方式将是类类型的行为和内部工作方式。


0
投票

发现这个讨论非常有帮助,我改进了原始代码并将其总结如下:

struct StructA
{
    // Not boxed.
    // Live wherever the StructA value will live.
    // Stored on stack if StructA value is a local variable;
    // Stored on heap when StructA is a property in a class.
    int structB;
}

class ClassB
{
    // Not boxed.
    // Stored on the heap.
    // Struct can be stored on the heap as part of another object.
    StructA structA;

    // Not boxed.
    // Stored on the heap.
    int classBField;
}
© www.soinside.com 2019 - 2024. All rights reserved.