C# 中的装箱和拆箱

本文关键字: | 更新日期: 2023-09-18 11:27:43

C# 有两种数据类型,value types and reference types .值类型存储值本身,而引用类型存储存储它的值的地址。一些预定义的数据类型(如 int、float、double、decimal、bool、char 等)是值类型,对象、字符串和数组是引用类型。

使用这些数据类型时,通常需要将值类型转换为引用类型,反之亦然。 由于两者具有不同的特征,并且 .NET 将它们以不同的方式存储在内存中,因此它必须在内部执行一些工作才能将它们从一种类型转换为另一种类型。这些转换过程称为装箱和拆箱。

什么是装箱?(What is boxing?)

装箱是将值类型转换为对象类型或由此值类型实现的任何接口类型的过程。装箱是隐含的。

int i = 10;
object o = i; //performs boxing

在上面的示例中,整数变量i被分配给对象o。由于对象类型是 C# 中所有类的引用类型和基类,因此可以将 int 分配给对象类型。 将 int 转换为对象的过程称为装箱。

让我们看一个更实际的例子。

ArrayList list = new ArrayList();
list.Add(10); // boxing
list.Add("Bill");

上面,ArrayList 是 C# 中的一个类,因此它是一个引用类型。我们在其中添加一个 int 值10。 因此,.NET 将在此处执行装箱过程,将值类型分配给引用类型。

为什么叫装箱?(Why named boxing?)

你可能想知道,为什么它被命名为装箱?

如您所知,存储在堆上的所有引用类型都包含值和值类型的地址,只是存储在堆栈上的实际值。 现在,如第一个示例所示,int i 被分配给对象 o 。对象o必须是地址,而不是值本身。 因此,CLR 通过在堆上创建一个新的 System.Object 来框住值类型,并将 i 的值包装在其中,然后将该对象的地址分配给 o 。 因此,由于 CLR 在存储值的堆上创建了一个框,因此整个过程称为"装箱"。

下图说明了装箱过程。

什么是拆箱?(What is Unboxing?)

拆箱与装箱相反。它是将引用类型转换为值类型的过程。拆箱 从引用类型中提取值并将其分配给值类型。

拆箱是明确的。这意味着我们必须显式投射。

object o = 10;
int i = (int)o; //performs unboxing

下图说明了拆箱过程。

装箱转换会复制该值。因此,更改一个变量的值不会影响其他变量。

int i = 10;
object o = i; // boxing
o = 20;
Console.WriteLine(i); // output: 10
.box-4-multi-148{border:none !important;display:block !important;float:none !important;line-height:0px;margin-bottom:15px !important;margin-left:auto !important;margin-right:auto !important;margin-top:15px !important;

不允许转换盒装值。以下内容将引发异常。

int i = 10;
object o = i; // boxing
double d = (double)o; // runtime exception

先做拆箱,再做铸造,如下图所示。

int i = 10;
object o = i; // boxing
double d = (double)(int)o; // valid

注意: 装箱和拆箱会降低性能。因此,请避免使用它。使用泛型以避免装箱和拆箱。例如,使用 List 而不是 ArrayList。

阅读这个关于堆栈溢出的有趣讨论:Why do we need boxing and unboxing in C#?


本文内容总结:

相关文章:
  • 没有找到相关文章