为什么我们需要在C#中装箱和拆箱?
我知道装箱和拆箱是什么,但我无法理解其实际用途。为什么在哪里使用?
short s = 25; object objshort = s; //Boxing short anothershort = (short)objshort; //Unboxing
为什么
要拥有统一的类型系统并允许值类型对其基础数据的表示形式与引用类型表示其基础数据的方式完全不同(例如,一个int只是三十二位的存储桶,它与引用完全不同)类型)。
int
这样想吧。您有一个otype 变量object。现在您有了一个,int并且想要将其放入o。o是对某处某物的引用,而int强调不是某处某物的引用(毕竟,它只是一个数字)。因此,您要执行的操作是:创建一个object可以存储的新int对象,然后将对该对象的引用分配给o。我们称此过程为“装箱”。
o
object
因此,如果您不关心拥有统一的类型系统(即,引用类型和值类型具有非常不同的表示形式,并且您不希望使用通用的方式“表示”这两者),则无需装箱。如果您不在乎int表示其基础值(即也int可以是引用类型,而仅存储对其基础值的引用),则无需装箱。
我应该在哪里使用它。
例如,旧的集合类型ArrayList只吃objects。也就是说,它仅存储对生活在某处的事物的引用。如果没有装箱,您将无法放入int这样的收藏中。但是使用拳击,您可以。
ArrayList
现在,在泛型时代,您实际上并不需要它,并且通常可以在不考虑问题的情况下轻松进行。但是需要注意一些注意事项:
这是对的:
double e = 2.718281828459045; int ee = (int)e;
这不是:
double e = 2.718281828459045; object o = e; // box int ee = (int)o; // runtime exception
相反,您必须执行以下操作:
double e = 2.718281828459045; object o = e; // box int ee = (int)(double)o;
首先,我们必须明确地取消double((double)o)的装箱,然后将其转换为int。
double
(double)o
以下是什么结果:
double e = 2.718281828459045; double d = e; object o1 = d; object o2 = e; Console.WriteLine(d == e); Console.WriteLine(o1 == o2);
在继续下一句话之前,请先考虑一下。
如果你说的True和False伟大!等一下 那是因为==在引用类型上使用引用相等性来检查引用是否相等,而不是基础值是否相等。这是容易犯的危险。也许更加微妙
True
False
==
double e = 2.718281828459045; object o1 = e; object o2 = e; Console.WriteLine(o1 == o2);
也会打印False!
最好说:
Console.WriteLine(o1.Equals(o2));
幸运的是,它将打印出来True。
最后一个微妙之处:
[struct|class] Point { public int x, y; public Point(int x, int y) { this.x = x; this.y = y; } } Point p = new Point(1, 1); object o = p; p.x = 2; Console.WriteLine(((Point)o).x);
输出是什么?这取决于!如果Point是,struct则输出为;1如果Point是,class则输出为2!装箱转换将复制装箱的值,以解释行为上的差异。
Point
struct
1
class
2