c# 数组的笔记
定义
- 元素:数组的独立数据项称作元素。数组的所有元素必须是相同类型的,或继承自相同的类型。
- 秩/维度:数组的维度数可以为任何正数。数组的维度数称作秩(rank)。
- 秩/维度:数组的维度数可以为任何正数。数组的维度数称作秩(rank)。
- 数组长度:数组的所有维度中的元素总数称为数组的长度。
重要细节
- 数组一旦创建,大小就固定了。c#不支持动态数组。
- 数组索引号是从0开始的。
数组类型
c#提供了两种类型的数组
- 一维数组可以认为是单行元素或元素向量。
- 多维数组是由主向量中的位置组成的,每一个位置本身又是一个数组,称为子数组(subarry)。另外,有两种类型的多维数组:矩形数组和交错数组:
矩形数组:
某个维度的所有子数组具有相同长度的多维数组。
不管有多少维度,总是使用一组方括号。
int x = myArray[4,6,1];//一组方括号
交错数组:
每一个子数组都是独立数组的多维数组。
可以有不同长度的子数组。
为数组的每一个维度使用一对方括号。
jagArray=[2][3][4];
数组是对象
数组实例是从System。Array继承类型的对象。由于数组从BCL基类派生而来,它们也继承了BCL基类中的很多有用的成员,如下所示。
- Rank :返回数组维度数属性。
- length:返回数组长度(数组中所有元素的个数)的属性。
数组是引用类型,但数组的元素既可以是值类型也可以是应用类型。 - 如果存储的元素都是值类型,数组被称为值类型数组。
- 如果是都是引类型,就被称为引用类型。
数组的声明
long[] secondArray;//long代表数组类型,[]里代表维度,没有","代表一维;
int[,,] arr1;//两个逗号代表三维;
long[3,2,6 ] arr2; //编译错误,不允许的维度长度
说明:和c/c++不同,方括号在基类型后,而不是在变量名称后。
实例化一维数组或矩形数组
int[] arr2 = new int[4];//arr2数组包含4个int的一维数组。4表式4个元素,在堆中是4个0;
MyClass[] mcArr = new MyClass[4];//mcArr数组是包含4个MyClass引用的一维数组。4在堆中是4个null;
int[,,] arr3 = new int[3,6,2];//arr3数组是三维数组,数组长度是3*6*2=36,可理解为在堆中有一个长宽高为3,6,2的长方体,有36个0;
说明:与对象创建表达式不一样,数组创建表达式不包括圆括号——即使是对于引用类型数组。
访问数组元素
int[] intArr1 = new int[15];//声明一维数组
intArr1[2] = 10;//向第3个元素写入值
int var1 =intArr1[2];//从第3个元素读取值
int[,] intArr2 = new int[5,10];//声明一个二维数组
intArr2[2,3] = 7;//向二维数组写入值
int var2 = intArr2[2,3];//从数组中读取值
int[] myIntArray;//声明
myIntArray = new int[4];//实例化数组
//设置值
for (int i = 0; i < 4; i++)
{
myIntArray[i] = i * 10;
}
//读取并输出每个数组元素的值
for (int i = 0; i < 4; i++)
{
Console.WriteLine($"Value of element {i} = {myIntArray[i]}");
}
Console.ReadLine();
输出:
Value of element 0 = 0
Value of element 1 = 10
Value of element 2 = 20
Value of element 3 = 30
初始化数组
显示初始化一维数组
- 初始值必须以逗号分隔,并封闭在一组大括号内。
- 不必输入维度长度,因为编译器可以通过初始化的个数来推断长度。
- 注意,在数组创建表达式和初始化列表中没有分隔符,也就是说,没有等号或其他方法练接运算符。
如下,创建一个数组,并将它的4个元素初始化为大括号内的值。
int[] intArr = new int[](10,20,30,40);
显示初始化矩形数组
- 每个初始值向量必须封闭在大括号内
- 每个维度也必须嵌套在打括号内
- 除初始值,每一个维度的初始化列表和组成部分也必须使用逗号分隔
如:
int[,] intArray2= new int[,]{{10,1},{2,10},{11,9}}
初始化矩形数组的语法点
矩形数组使用嵌套的、逗号分隔的初始化列表进行初始化。初始化列表嵌套在大括号内。这有时会造成混淆,因此,对于嵌套、分组和逗号的正确使用,如下例子:
int[,,] intArray = new int[4,3,2]{
{{8,6},{5,2},{12,9}},
{{6,4},{13,9},{18,4}},
{{7,2},{1,13},{9,3}},
{{4,6},{3,2},{23,8}}
}
快捷语法
int[] arr1 = new int[3]{10,20,30}
int[,] arr = new int[2,3]{{0,1,2},{10,11,12}}
等价于
int[] arr1 = {10,20,30}
int[,] arr ={{0,1,2},{10,11,12}}
隐式类型数组
- 编译器可以推断数组类型
- 和隐式类型的局部变量一样,使用var关键字来替代数组类型
显式
注意在intArr4中还是需要秩说明符
int[,] intArr3 = new int[,]{{10,1},{2,10},{11,9}}
隐式
var intArr4 = new [,]{{10,1},{2,10},{11,9}}
综合内容
创建一个矩形数组,并对其进行初始化
//声明、创建和初始化一个隐式类型的数组
var arr = new int[,] { { 0,1,2}, { 10,11,12} };
//输出值
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3:j++)
{
Console.WriteLine($"Element[ {i},{j}] is {arr[i, j]}");
}
}
Console.ReadLine();
输出:
Element[ 0,0] is 0
Element[ 0,1] is 1
Element[ 0,2] is 2
Element[ 1,0] is 10
Element[ 1,1] is 11
Element[ 1,2] is 12
交错数组
交错数组是数组的数组。与矩形数组不同,交错数组的子数组的元素个数可以不同。
…
foreach
- 从数组的第一个元素开始并把它赋值给迭代变量
- 然后执行语句主体。在主体中,我们可以把迭代变量作为数组元素的只读别名
迭代变量是只读的
对于值类型数组,我们不能改变
下面代码会编译错误
int[] arr1 = {10,20,30,40};
foreach(int item in arr1)
item++;
对于引用类型数组,仍不可改变迭代变量,但迭代变量只是保存了数据的引用,而不是数据本身,因此,虽不能改变引用,但我们可以通过迭代变量改变数据。
如下代码创建了一个有4个MyClass对象的数组并将其初始化。在第一个foreach语句中,改变了每一个对象中的数据。在第二个foreach语句中,从对象读取改变后的值。
class MyClass
{
public int MyField = 0;
}
class Program
{
static void Main(string[] args)
{
MyClass[] mcArray = new MyClass[4];//创建数组
for (int i = 0; i < 4; i++)
{
mcArray[i] = new MyClass();//创建类对象
mcArray[i].MyField = i;//设置字段
}
foreach (MyClass item in mcArray)
{
item.MyField += 10;//改变数据
}
foreach (MyClass item in mcArray)
{
Console.WriteLine($"{item.MyField}");//读取改变的数据
}
Console.ReadLine();
}
}
输出:
10
11
12
13
foreach语句和多维数组
在多维数组中,元素的处理次序是最右边的索引号最先递增。当索引从0到长度减1时,开始递增它左边的索引,右边的索引被重置成0。
int total = 0;
int[,] arr1 = { {10,11 }, {12,13 } };
foreach (var element in arr1)
{
total += element;
Console.WriteLine($"Element:{element},Current Total:{total}");
}
输出:
Element:10,Current Total:10
Element:11,Current Total:21
Element:12,Current Total:33
Element:13,Current Total:46
数组继承的有用成员
c#数组派生自System.Array类
成员 | 类型 | 生存期 | 意义 |
---|---|---|---|
Rank | 属性 | 实例 | 获取数组的维度数 |
Length | 属性 | 实例 | 获取数组中所有的维度的元素总数 |
GetLength | 方法 | 实例 | 返回数组的指定维度的长度 |
Clear | 方法 | 静态 | 将某一范围内的元素设置为0或1 |
Sort | 方法 | 静态 | 在一维数组中对元素进行排序 |
BinarySearch | 方法 | 静态 | 使用二进制搜索,搜索一维数组中的值 |
Clone | 方法 | 进行数组的浅复制——对于值类型数组和引用类型数组,都只复制元素 | |
IndexOf | 方法 | 静态 | 返回一维数组中遇到的第一个值 |
Reverse | 方法 | 静态 | 反转一维数组中的某一范围的元素 |
GetUpperBound | 方法 | 实例 | 获取指定维度的上限 |
public static void PrintArray(int[] a)
{
foreach (var x in a)
Console.Write($"{x} ");
Console.WriteLine(" ");
}
static void Main(string[] args)
{
int[] arr = new int[] { 15,20,5,25,10};
PrintArray(arr);
Array.Sort(arr);
PrintArray(arr);
Array.Reverse(arr);
PrintArray(arr);
Console.WriteLine();
Console.WriteLine($"Rank={arr.Rank},Length={arr.Length}");
Console.WriteLine($"GetLength(0)={arr.GetLength(0)}");
Console.WriteLine($"GetType()={arr.GetType()}");
Console.Read();
}
输出:
15 20 5 25 10
5 10 15 20 25
25 20 15 10 5
Rank=1,Length=5
GetLength(0)=5
GetType()=System.Int32[]
Clone方法
Clone方法为在数组进行浅复制,也就是说,他只是创建了数组本身的克隆。如果是引用类型数组,它不会复制元素引用对象。对于值类型数组和引用类型的对象。对于值类型数组和引用类型数组而言,这有不同的结果。
- 克隆值类型数组会产生两个独立数组。
- 克隆引用类型数组会产生指向相同对象的两个数组。
class A
{
public int Value = 5;
}
class Program
{
static void Main(string[] args)
{
A[] AArray1 = new A[3]{ new A(),new A(),new A()};//步骤1
A[] AArray2 = (A[])AArray1.Clone();//步骤2
AArray2[0].Value = 100;
AArray[1].Value = 200;
AArray[2].Value = 300; //步骤3
}
}