在.NET中装箱/拆箱

l--*_*''' 3 .net c#

看起来很重要的是拳击和拆箱.对象类型有这么多用途我们真的要非常清楚这一点吗?

什么是需要装箱/拆箱的实际情况?

Ree*_*sey 13

这取决于.

我认为它目前不像以前那么重要.如果您确保在框架内使用泛型集合(即:使用List<T>而不是ArrayList),那么它可能不会成为您的主要问题.

这是.NET 1.1 中的一个大问题,因为大多数集合都在使用object,因为没有通用集合.在.NET 1.1中,你每增加一个时间int,例如,为大多数集合,它得到了盒装,每一次你拉出来的时候,它是拆箱.如果你在紧密的循环中这样做,很容易出现问题.它还导致许多错误,例如尝试取消装箱并转换为不合适的类型,这会引发异常.


区别在于:

在.NET 1.1中,您通常会使用类似于ArrayList:

ArrayList list = new ArrayList();

list.Add(1); // These are all boxing - the integer is getting boxed to add
list.Add(2);   
list.Add(3);

foreach(object item in list)
{
    // Unboxing required here:
    int value = (int)item;
    Console.WriteLine(value);
}
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,由于这不是类型安全的,因此您可能很容易导致严重的问题,因为在单个操作中不会发生unbox和转换:

foreach(object item in list)
{
    // Trying to unboxing into the wrong type here...
    // This will raise an exception at runtime, but compile fine!
    double value = (double)item;
    Console.WriteLine(value);
}
Run Code Online (Sandbox Code Playgroud)

但是,在.NET 2及更高版本中,您可以使用泛型集合:

List<int> list = new List<int>();


list.Add(1); // No boxing now, since it's using generics!
list.Add(2);   
list.Add(3);

foreach(int value in list) // This is now typesafe, and doesn't cause an unboxing operation
{
    Console.WriteLine(value);
}
Run Code Online (Sandbox Code Playgroud)

有时今天仍然需要拳击和拆箱.例如,Reflection完全依赖于object具体类型,而不是具体类型,因此需要装箱值才能使用FieldInfo.SetValue等方法.

  • @SaeedAlg:通用约束(`其中T:X`)实际上与拳击无关,也不会导致拳击. (2认同)