在.net中对象的装箱处于什么级别?

时间:2012-01-12 16:24:20

标签: c# .net boxing

如果我有一个List<string>这样的对象,我将其转换为object,然后再返回,是否所有字符串都会被转换,或者仅包含它们的列表?

我认为编译器只需检查object是否为List<string>类型,然后再转回List<string>但我在C#中长大,所以我'我不完全确定我写的代码背后发生了什么。

6 个答案:

答案 0 :(得分:6)

当你将List<string>投射到object时,你根本就没有做任何投射。您将一些数据的引用分配给一个不太具体的引用。它包含的string个对象也没有改变。


此外,澄清一下,在这种情况下没有拳击。当您创建对int或某些struct等值类型的引用时,通过分配或以某种方式将其传递给object类型的变量,就会发生拳击。

答案 1 :(得分:3)

当结构/值类型存储在键入到对象的位置或该结构实现的接口时,就会发生拳击。在这种情况下,List<string>string都是引用类型,因此不会发生装箱。

struct S1 : IComparable {
  ...
}

S1 local = new S1();  // No box. 
object obj = local;   // Box S1 instance into object
IComparable comp = local;  // Box S1 instance into IComparable
obj = "hello";  // String is a reference type, no boxing

答案 2 :(得分:2)

string是一种引用类型 - string的实例永远不会被装箱。

如果你有一个List<int>,那么List就是一个引用类型,所以这里也没有装箱。 int是一个值类型,如果它被强制转换为对象(隐式或显式),它可以被装箱。

Boxing只影响值类型 - List<T>是一个类,因此是一个引用类型,更改泛型类型T不会影响实例是按值传递还是通过引用传递。

通用集合有助于防止装箱,因为它可以读取/写入值类型,而不会被装箱到object

答案 3 :(得分:1)

对于每种值类型,都有一个具有相同名称的相应对象类型,该类型派生自ValueType。每当需要创建给定类型的存储位置(字段,变量或参数)时,系统将分配空间来存储堆引用(如果类型不是从ValueType派生的),所有类型的字段(如果它是'struct'),或者是持有类型值的位。当尝试将值类型的实例存储到堆引用中时,会发生Boxing。当尝试使用堆引用时,就会发生取消装箱,就好像它是值类型一样。请注意,在某些上下文中,取消装箱会将装箱对象的内容复制到新的存储位置,但在其他上下文中,它会将装箱的实例视为存储位置。这种语义并不总是很清楚,这是一些人讨厌可变结构的原因之一。在实践中,如果避免使用语义变得模糊的使用场景,可变结构就可以了,甚至不可变结构也会受到同样模糊语义的影响。

答案 4 :(得分:0)

只会投放List<string>

如果你想要投射List<string>项,请执行以下操作:

List<string> list = new List<string>{"first", "second"};
List<object> objectsList = list.Cast<object>();

P.S。 string是一种引用类型,因此无法真正获得boxedunboxed

答案 5 :(得分:0)

Boxing和Unboxing是适用于值类型而非参考类型的操作。

不是这样,它只是一个简单的演员。