# 数组与集合 ## 数组 可以将同一类型的多个变量存储在一个数组数据结构中。 通过指定数组的元素类型来声明数组。 如果希望数组存储任意类型的元素,可将其类型指定为 `object`。 语法: ```csharp type[] arrayName; ``` 数组具有以下属性: - 数组可以是[一维](https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/arrays/single-dimensional-arrays)、[多维](https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/arrays/multidimensional-arrays)或[交错](https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/arrays/jagged-arrays)的。 - 创建数组实例时,将建立纬度数量和每个纬度的长度。 这些值在实例的生存期内无法更改。 - 数值数组元素的默认值设置为零,而引用元素设置为 null。 - 交错数组是数组的数组,因此其元素为引用类型且被初始化为 `null`。 - 数组从零开始编制索引:包含 `n` 元素的数组从 `0` 索引到 `n-1`。 - 数组元素可以是任何类型,其中包括数组类型。 - 数组类型是从抽象的基类型 [Array](https://docs.microsoft.com/zh-cn/dotnet/api/system.array) 派生的[引用类型](https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/reference-types)。 所有数组都会实现 [IList](https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.ilist) 和 [IEnumerable](https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.ienumerable)。 可在 C# 中使用 [foreach](https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/statements/iteration-statements#the-foreach-statement) 迭代数组。 原因是单维数组还实现了 [IList](https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.generic.ilist-1) 和 [IEnumerable](https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.generic.ienumerable-1)。 ### 一维数组 使用 [new](https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/new-operator) 运算符创建一维数组,该运算符指定数组元素类型和元素数目。 以下示例声明一个包含五个整数的数组: ```csharp int[] array = new int[5]; ``` 此数组包含从 `array[0]` 到 `array[4]` 的元素。 数组元素将初始化为元素类型的默认值,`0` 代表整数。 #### 数组初始化 可以在声明数组时初始化数组的元素。 不需要长度说明符,因为可以根据初始化列表中的元素数量推断得出。 例如: ```csharp int[] array1 = new int[] { 1, 3, 5, 7, 9 }; ``` 在声明时初始化数组时,可以避免使用 `new` 表达式和数组类型,如以下代码所示。 这称为[隐式类型化数组](https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/arrays/implicitly-typed-arrays): ```csharp int[] array2 = { 1, 3, 5, 7, 9 }; string[] weekDays2 = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; ``` ### 多维数组 数组可具有多个维度。 例如,以下声明创建一个具有四行两列的二维数组。 ```csharp int[,] array = new int[4, 2]; ``` 以下声明创建一个具有三个维度(4、2 和 3)的数组。 ```csharp int[,,] array1 = new int[4, 2, 3]; ``` #### 数组初始化 声明后即可初始化数组,如以下示例所示。 ```csharp // Two-dimensional array. int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // The same array with dimensions specified. int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; // A similar array with string elements. string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" }, { "five", "six" } }; // Three-dimensional array. int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; // The same array with dimensions specified. int[,,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } }; // Accessing array elements. System.Console.WriteLine(array2D[0, 0]); System.Console.WriteLine(array2D[0, 1]); System.Console.WriteLine(array2D[1, 0]); System.Console.WriteLine(array2D[1, 1]); System.Console.WriteLine(array2D[3, 0]); System.Console.WriteLine(array2Db[1, 0]); System.Console.WriteLine(array3Da[1, 0, 1]); System.Console.WriteLine(array3D[1, 1, 2]); // Getting the total count of elements or the length of a given dimension. var allLength = array3D.Length; var total = 1; for (int i = 0; i < array3D.Rank; i++) { total *= array3D.GetLength(i); } System.Console.WriteLine("{0} equals {1}", allLength, total); // Output: // 1 // 2 // 3 // 4 // 7 // three // 8 // 12 // 12 equals 12 ``` 还可在不指定级别的情况下初始化数组。 ```csharp int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; ``` ### 交错数组 交错数组是一个数组,其元素是数组,大小可能不同。 交错数组有时称为“数组的数组”。 以下示例说明如何声明、初始化和访问交错数组。 下面声明一个具有三个元素的一维数组,其中每个元素都是一维整数数组: ```csharp int[][] jaggedArray = new int[3][]; ``` 必须初始化 `jaggedArray` 的元素后才可使用它。 可按下方操作初始化元素: ```csharp jaggedArray[0] = new int[5]; jaggedArray[1] = new int[4]; jaggedArray[2] = new int[2]; ``` 每个元素都是一维整数数组。 第一个元素是由 5 个整数组成的数组,第二个是由 4 个整数组成的数组,而第三个是由 2 个整数组成的数组。 ### 遍历数组 可以使用foreach语句来遍历数组。 对于单维数组,`foreach` 语句以递增索引顺序处理元素(从索引 0 开始并以索引 `Length - 1` 结束): ```csharp int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 }; foreach (int i in numbers) { System.Console.Write("{0} ", i); } // Output: 4 5 6 1 2 3 -2 -1 0 ``` 对于多维数组,遍历元素的方式为:首先增加最右边维度的索引,然后是它左边的一个维度,以此类推,向左遍历元素: ```csharp int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } }; // Or use the short form: // int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } }; foreach (int i in numbers2D) { System.Console.Write("{0} ", i); } // Output: 9 99 3 33 5 55 ``` ## Hastable > Hashtable 类代表了一系列基于键的哈希代码组织起来的**键/值**对。它使用**键**来访问集合中的元素。 语法: ```csharp Hastable ht = new Hashtable(); ``` ### 属性 | 属性 | 描述 | | :---------- | :-------------------------------------------- | | Count | 获取 Hashtable 中包含的键值对个数。 | | IsFixedSize | 获取一个值,表示 Hashtable 是否具有固定大小。 | | IsReadOnly | 获取一个值,表示 Hashtable 是否只读。 | | Item | 获取或设置与指定的键相关的值。 | | Keys | 获取一个 ICollection,包含 Hashtable 中的键。 | | Values | 获取一个 ICollection,包含 Hashtable 中的值。 | ### 方法 | 方法 | 描述 | | ---------------------------- | ------------------------------------------- | | Add(object key,object value) | 向Hashtable中添加一个元素,如果键重复则报错 | | Clear() | 清除Hashtable中所有的元素 | | ContainsKey(object key) | 判断Hashtable中是否包含指定的键 | | ContainValue(object value) | 判断Hashtable中是否包含指定的值 | | Remove(object key) | 从Hashtable中移除指定键的元素 |