自学内容网 自学内容网

深入解析C#中的ArrayList、装箱和拆箱

深入解析C#中的ArrayList、装箱和拆箱


一、什么是ArrayList?

ArrayList是C#中一种集合类型,位于System.Collections命名空间下。它的功能类似于数组,可以存储多个元素,但与数组不同的是,ArrayList的大小是可动态改变的,你可以随时添加或删除元素。

特点:

  • 非泛型集合ArrayList是非泛型的,这意味着它可以存储任何类型的对象。
  • 元素类型为objectArrayList内部存储的元素类型为object

示例:

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        ArrayList list = new ArrayList();
        list.Add(10);         // 添加整数
        list.Add("Hello");    // 添加字符串
        list.Add(3.14);       // 添加小数

        foreach (var item in list)
        {
            Console.WriteLine(item);
        }
    }
}

输出:

10
Hello
3.14

二、什么是装箱和拆箱?

在C#中,数据类型分为值类型引用类型

  • 值类型:直接存储数据的值。例:intdoubleboolstruct等。
  • 引用类型:存储的是数据的引用(内存地址)。例:objectstringclass等。

装箱(Boxing):

值类型转换为引用类型的过程,称为装箱。简单来说,就是把一个值类型的值包装到object类型的引用中。

拆箱(Unboxing):

引用类型转换回值类型的过程,称为拆箱。也就是从object类型的引用中提取出原始的值类型的值。


三、为什么ArrayList会涉及装箱和拆箱?

由于ArrayList的元素类型是object,当我们向其中添加值类型的数据(如intdouble)时,需要将值类型装箱为引用类型(object)才能存储。

当从ArrayList中取出元素,并赋值给值类型的变量时,需要将object类型的引用拆箱为值类型。


四、实例解析装箱和拆箱

1. 装箱的实例

int num = 100;
object obj = num; // 发生装箱,将int类型的num装箱为object类型的obj
Console.WriteLine(obj);

在这段代码中,num是一个int类型的值类型变量。当我们将num赋值给object类型的obj时,发生了装箱操作。

2. 拆箱的实例

object obj = 100;    // 装箱,100是int类型的值,被装箱为object类型
int num = (int)obj;  // 拆箱,将object类型的obj拆箱为int类型的num
Console.WriteLine(num);

这里,obj最初存储了一个装箱后的int值。当我们想把obj的值赋给int类型的变量时,需要进行强制类型转换,即拆箱操作。

注意:

  • 装箱是隐式的,编译器会自动完成。
  • 拆箱是显式的,需要进行强制类型转换,否则会出现编译错误或运行时错误。

3. 在ArrayList中的装箱和拆箱

using System;
using System.Collections;

class Program
{
    static void Main()
    {
        ArrayList list = new ArrayList();

        int num1 = 10;
        double num2 = 3.14;

        list.Add(num1); // 装箱int类型
        list.Add(num2); // 装箱double类型

        // 从ArrayList中取出元素,需要拆箱
        int retrievedNum1 = (int)list[0];
        double retrievedNum2 = (double)list[1];

        Console.WriteLine(retrievedNum1); // 输出:10
        Console.WriteLine(retrievedNum2); // 输出:3.14
    }
}

在以上代码中:

  • 添加num1num2ArrayList时,发生了装箱。
  • ArrayList中取出元素时,必须进行强制类型转换(拆箱),否则编译器不知道如何将object类型转换为具体的值类型。

五、装箱和拆箱的性能问题

装箱和拆箱会带来一定的性能开销,原因是:

  • 装箱:需要在托管堆上分配内存,将值类型的值复制到新分配的内存中。
  • 拆箱:需要从托管堆中读取数据,并进行类型检测,确保类型安全。

在频繁进行装箱和拆箱的情况下,会影响程序的性能,增加垃圾回收的负担。


六、如何避免装箱和拆箱?

为了解决装箱和拆箱带来的性能问题,C#引入了泛型集合,如List<T>。泛型集合可以在编译时确定类型,避免了装箱和拆箱操作。

示例:使用List代替ArrayList

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> list = new List<int>();

        int num1 = 10;
        list.Add(num1); // 不需要装箱

        int retrievedNum = list[0]; // 不需要拆箱
        Console.WriteLine(retrievedNum); // 输出:10
    }
}

优点:

  • 类型安全List<int>只能存储int类型的数据,避免了类型转换错误。
  • 性能更佳:不涉及装箱和拆箱操作,减少了性能开销。
  • 代码更简洁:不需要进行强制类型转换,代码更清晰。

七、小结

  • ArrayList是非泛型集合,可以存储任何类型的数据,但对于值类型,会发生装箱和拆箱操作。
  • 装箱是将值类型转换为引用类型的过程,拆箱是将引用类型转换回值类型的过程。
  • 装箱和拆箱会带来性能开销,应尽量避免频繁使用。
  • **泛型集合(如List)**可以避免装箱和拆箱,提高程序性能和类型安全性。

希望以上的解释和实例能够帮助你理解ArrayList和装箱、拆箱的概念。作为C#初学者,建议你在实际编程中多练习,体会其中的差别和影响。


原文地址:https://blog.csdn.net/dgwxligg/article/details/144370071

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!