拳击和拆箱:什么时候出现?

Chr*_*ris 14 c# boxing object

所以我明白拳击和拆箱是什么.什么时候出现在现实世界的代码中,或者在什么样的例子中出现问题?我无法想象做这样的事情:

int i = 123;
object o = i;           // Boxing
int j = (int)o;     // Unboxing
Run Code Online (Sandbox Code Playgroud)

...但这几乎肯定是极度过于简单的,我甚至可能在之前不知道它的情况下完成了装箱/拆箱.

Jon*_*eet 34

这是很多现在不再是一个问题比它之前的仿制药.现在,例如,我们可以使用:

List<int> x = new List<int>();
x.Add(10);
int y = x[0];
Run Code Online (Sandbox Code Playgroud)

根本不需要拳击或拆箱.

以前,我们有:

ArrayList x = new ArrayList();
x.Add(10); // Boxing
int y = (int) x[0]; // Unboxing
Run Code Online (Sandbox Code Playgroud)

这是最常见的拳击和拆箱经验,至少.

如果没有泛型参与,我想我可能会说反思是我参与的项目中拳击的最常见原因.反射API总是使用"对象"来表示方法的返回值 - 因为它们没有其他方法可以知道要使用什么.

如果您不了解它,可能会发现的另一个原因是您使用实现接口的值类型,并将该值传递给另一个以接口类型作为参数的方法.同样,泛型使这不是一个问题,但如果你不知道它,它可能是一个令人讨厌的惊喜.

  • "我想我可能会说反思是我参与过的项目中拳击最常见的原因" - 当然,这在很大程度上取决于项目的类型.例如,如果您使用WPF或Silverlight,则在使用值转换器(IValueConverter接受并返回对象),依赖项属性(DependencyObject.GetValue和SetValue返回并获取对象)等时,将一直*进行装箱. (7认同)

And*_*are 8

拳击(根据我的经验)通常发生在这些情况下:

  • 值类型将传递给接受类型参数的方法Object.
  • 值类型将添加到非泛型集合(如an ArrayList).

其他时候你可以看到装箱和拆箱是因为.NET框架的反射API大量使用反射Object.


LBu*_*kin 5

当将值类型(如struct,int,long)传递给接受引用类型的位置时,就会发生装箱/拆箱object

当您显式创建一个采用将传递值类型的object类型参数的方法时,会发生这种情况。当您使用较旧的非泛型集合来存储值类型(通常是基元)时,也会出现这种情况。

使用String.Format()和传递原语时,您还将看到拳击发生。这是因为String.Format()接受params object []-导致在调用中将其他参数装箱。

使用反射调用方法也可能导致装箱/拆箱,因为反射API只能选择返回,object因为在编译时不知道实类型(并且反射API不能是泛型的)。

较新的通用集合不会导致装箱/拆箱,因此出于这个原因,较之较旧的集合(例如ArrayList,Hashtable等)更可取。更不用说它们是类型安全的。

您可以通过更改接受通用对象的方法来避免装箱问题。例如:

public void string Decorate( object a ) // passing a value type results in boxing
{
   return a.ToString() + " Some other value";
}
Run Code Online (Sandbox Code Playgroud)

vs:

public void string Decorate<T>( T a )
{
   return a.ToString() + " some other value";
}
Run Code Online (Sandbox Code Playgroud)