• 【读书笔记】C#高级编程 第六章 数组


    (一)同一类型和不同类型的多个对象

    如果需要使用同一类型的多个对象,就可以使用数组或集合(后面章讲)。

    如果需要使用不同类型的多个对象,可以使用Tuple(元组)类型。

    (二)简单数组

    如果需要使用同一类型的多个对象,可以使用数组。数组是一种结构,它可以包含同一类型的多个元素。

    1、数组的声明

    在声明数组时,应先定义数组总元素的类型,其后是一堆空方括号和一个变量名。

    例子:

    以下代码声明了一个包含整形类型的数组

    int[] intArray;

     

    2、数组的初始化

    声明了数组后,就必须为数组分配内存,以保存数组的所有元素。数组是引用类型,所以需要分配的是堆上的内存。为此,应使用new关键字,指定数组中元素的类型和数量来初始化数组的变量。

    例子:

    intArray = new int[10];

    除了以上方式初始化,还有如下方式:

    int[] intArray = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    
    int[] intArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    
    int[] intArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

     

    3、访问数组元素

    在声明和初始化数组后,就可以使用索引器访问其中的元素了。数组只支持有整型参数的索引器。

    通过索引器传递元素编号,就可以访问数组。索引器总是以0开头,表示第一个元素。可以传递给索引器的最大值是元素个数减1,因为索引从0开始。

    int[] intArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    
    int x = intArray[6];//7
    
    int y = intArray[9];//0

    还可以使用for循环访问:

    for (int i = 0; i < intArray.Length; i++)
    
    {
    
        Console.WriteLine(intArray[i]);
    
    }

    除了for循环还可以用foreach循环:

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

    4、使用引用类型

    除了能声明预定义类型的数组,还可以声明自定义类型的数组。

    Person[] personArray = new Person[3];

    初始化后可以使用索引器为元素赋值:

    personArray[0] = new Person();
    
    personArray[1] = new Person();
    
    personArray[2] = new Person();

    (三)多维数组

    一般数组(也称为一维数组)用一个整数来索引。多维数组用两个或多个整数来索引。

    声明多维数组,需要在方括号中加上逗号。

    例子:

    声明二维数组

    int[,] intTwoDim = new int[3, 3];
    
    intTwoDim[0, 0] = 1;
    
    intTwoDim[0, 1] = 2;
    
    intTwoDim[0, 2] = 3;
    
    intTwoDim[1, 0] = 4;
    
    intTwoDim[1, 1] = 5;
    
    intTwoDim[1, 2] = 6;
    
    intTwoDim[2, 0] = 7;
    
    intTwoDim[2, 1] = 8;
    
    intTwoDim[2, 2] = 9;

    例子:

    声明三维数组

    int[,,] intTwoDim = new int[2, 2, 2];
    
    intTwoDim[0, 0, 1] = 1;
    
    intTwoDim[0, 0, 2] = 2;
    
    intTwoDim[0, 1, 1] = 3;
    
    intTwoDim[0, 1, 2] = 4;
    
    intTwoDim[0, 2, 1] = 5;
    
    intTwoDim[0, 2, 2] = 6;
    
    intTwoDim[1, 0, 1] = 7;
    
    intTwoDim[1, 0, 2] = 8;
    
    intTwoDim[1, 1, 1] = 9;
    
    intTwoDim[1, 1, 2] = 10;
    
    intTwoDim[1, 2, 1] = 11;
    
    intTwoDim[1, 2, 2] = 12;
    
    intTwoDim[2, 0, 1] = 13;
    
    intTwoDim[2, 0, 2] = 14;
    
    intTwoDim[2, 1, 1] = 15;
    
    intTwoDim[2, 1, 2] = 16;
    
    intTwoDim[2, 2, 1] = 17;
    
    intTwoDim[2, 2, 2] = 18;

    需要注意的是,声明数组后,就不能修改其阶数来了,并且数组使用初始化时,必须初始化数组的每个元素,不能遗任何元素。

    (四)锯齿数组

    多维数组的大小对应一个矩形,而锯齿数组的大小设置就比较灵活,在锯齿数组中,每一行都可以有不同的大小。

    在声明锯齿数组时,要一次放置左右括号。在初始化锯齿数组时,只在第一对方括号中设置该数组包含的行数。定义各行中元素个数的第2个方括号设置为空,因为这类数组的每行包含的个数可能不同,需要用索引器进行赋值。

    例子:

    int[][] intJagged = new int[2][];
    
    intJagged[0] = new int[1] { 1 };
    
    intJagged[1] = new int[5] { 1, 2, 3, 4, 5 };
    
    intJagged[2] = new int[2] { 1, 2 };

     

    (五)Array类

    用方括号声明数组其实是C#中使用Array类的表示法。

    1、创建数组

    Array类是一个抽象类,所以不能使用构造函数来创建数组。但除了可以使用C#语法创建数组实例外,还可以使用静态方法CreateInstance()创建数组。

    例子:

    Array intArray = Array.CreateInstance(typeof(int), 2);//创建数组
    
    intArray.SetValue(1, 0);//使用setvalue赋值
    
    intArray.SetValue(2, 1);
    
    int[] intNewArray = (int[])intArray;//可以转化为int[]形式

     

    2、复制数组

    因为数组是引用类型,所以将一个数组变量赋予另一个数组变量,就会得到两个引用同一个数组的变量。复制数组可以使用Clone()方法或Copy()方法,它们的区别是Clone()方法会创建一个新的数组,而Copy()方法必须传递阶数相同且有足够元素的已有数组,但它们都是浅表复制。

    如果需要包含引用类型的数组的深层副本,就必须迭代数组并创建新对象。

    3、排序

    Array类使用QuickSort算法对数组中的元素进行排序。Sort方法需要数组的元素实现IComparable接口,因为简单类型(string,int)实现了该接口所以可以排序。但自定义类型需要实现IComparable接口才能进行排序。

    例子:

    int[] intArray = { 21,3291,12,392,39,92,193};
    
    Array.Sort(intArray);
    
    foreach (var item in intArray)
    
    {
    
        Console.WriteLine(item);
    
    }

    运行以上代码,结果如下:

     

     

    (六)数组作为参数

    数组可以作为参数传递给方法,也可以从方法中返回。

    例子:

    public static int[] ArraySort(int[] array)
    
    {
    
        Array.Sort(array);
    
        return array;
    
    }

    1、数组协变

    数组支持协变。这表示数组可以声明为基类,其派生类型的元素可以赋予数组元素。但数组协变只能用于引用类型,不能用于值类型。另外数组协变传入的参数如果不能满足方法内的条件,也只能在运行时通过抛出异常来解决。

    2、ArraySegment<T>

    结构ArraySegment<T>表示数组的一段,其包含关于数组段的偏移量和元素个数信息。

    例子:

    int[] intArray = { 0, 1, 2, 3, 4, 5 };
    
    var intArraySegment = new ArraySegment<int>(intArray, 2, 2);
    
    foreach (var item in intArraySegment)
    
    {
    
        Console.WriteLine(item);
    
    }

    运行以上代码,结果如下:

     

    需要注意的是,数组段不复制原数组的元素。

    (七)枚举

    1、IEnumerator接口

    foreach语句使用IEnumerator接口的方法和属性,迭代集合中的所有元素。

    泛型版本的IEnumerator<T>接口派生自IDisposable,因此定义了Dispose()方法,来清理枚举器占用的资源。

    2、foreach语句

    C#编译器会把foreach语句转化为IEnumerable接口的方法和属性。

    例子:

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

    编译器会对foreach语句进行解析:

    IEnumerator<int> enumerator = intArray.GetEnumerator();
    
    while (enumerator.MoveNext())
    
    {
    
        int i = enumerator.Current();
    
        Console.WriteLine(i);
    
    }

    3、yield语句

    C#2.0添加了yield语句,以便于创建枚举器。yield return语句返回集合的一个元素,并移动到下一个元素上。yield break可停止迭代。

    例子:

    首先定义一个返回类型为IEnumertor<T>的GetEnumertor的方法

    public class PersonCollection
    
    {
    
        public IEnumerator<string> GetEnumerator()
    
        {
    
            yield return "张三";
    
            yield return "李四";
    
            yield return "王麻子";
    
            yield return "赵六";
    
        }
    
    }

    然后就可以使用foreach语句迭代集合了

    PersonCollection personCollection = new PersonCollection();
    
    foreach (var item in personCollection)
    
    {
    
        Console.WriteLine(item);
    
    }

    运行以上代码,结果如下:

     

    yield语句会生成一个枚举器,而不仅仅生成一个包含的项的列表。这个枚举器通过foreach语句调用。从foreach中依次访问每一项时,就会访问枚举器。这样就可以迭代大量的数据,而无需一次把所有的数据都读入内存中。

    (八)元组

    数组合并了相同类型的对象,元组合并了不同类型的对象。.NET Framework定义了8个泛型Tuple类和一个静态Tuple类,它们用作元组的工厂。元组用静态Tuple类的静态Create()方法创建。

    var result = Tuple.Create<int, int>(1, 2);//创建2个参数的元组
    
    var result1 = Tuple.Create<int, int, int, int, int, int, int, Tuple<int, int, int>>(1, 2, 3, 4, 5, 6, 7, Tuple.Create<int, int, int>(8, 9, 0));//创建10个(7个以上)参数的元组
    
    var result_item = result.Item1;
    
    var result1_item10 = result1.Rest.Item1.Item3;//访问2个参数元组的第一个参数

     

    (九)结构比较

    数组和元组都实现接口IStructuralEquatableIStructuralComparable。这两个接口都是.NET 4新增的,不仅可以比较引用,还可以比较内容。这些接口都是显示实现的,所以在使用时需要把数组和元组强制转换为这个接口。IStructuralEquatable接口用于比较两个元组或数组是否有相同的内容,IStructuralComparable接口用于给元组或数组排序。

    (十)小结

    本章介绍了创建和使用简单数组、多维数组和锯齿数组的C#表示法。C#数组在后台使用Array类,这样就可以用数组变量调用这个类的属性和方法。

    探讨了如何使用IComparableIComparaer接口给数组中的元素排序,描述了如何使用和创建枚举器、IEnumerableIEnumerator接口,以及yield语句。

    最后介绍了如何在数组中组织相同类型的对象,在元组中组织不同类型的对象。

  • 相关阅读:
    PowerShell里的数组
    题解 cf gym 103261 D FFT Algorithm
    欧拉筛求积性函数的一般形式
    题解 LOJ 6053
    题解 SP34112 UDIVSUM
    题解 luogu P5162 WD与积木
    Java 关闭流同步输入输出
    题解 luogu P6620 [省选联考 2020 A 卷] 组合数问题
    hdu 6588 题解
    题解 cf gym 102979 E Expected Distance
  • 原文地址:https://www.cnblogs.com/dlxh/p/6624689.html
Copyright © 2020-2023  润新知