数组具有以下属性:
数组可以静态定义,也可以隐式定义
int[] array = new int[5];
int[] array1 = new int[] { 1, 3, 5, 7, 9 }; // 定长为5,不是动态的
int[] array2 = { 1, 3, 5, 7, 9 }; // 定长
string[] weekDays2 = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
与其他语言定义数组不同,定义多维数组使用的是[,]
,其中每多一个问号多一个维度。在C#中[][]
并不是定义的多维数组,而是交错数组,也就是数组中的数组。
int[,] array = new int[4, 2]; //4 * 3 的二维数组
int[,,] array1 = new int[4, 2, 3]; // 4 * 2 * 3 的三维数组
显式定义多维数组的时候,必须全部定义完。
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
{ "five", "six" } };
隐式定义
int[,,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
不指定级别也能定义
int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
交错数组被称为数组中的数组,其内部往往定义了多个数组。
下列定义了一个交错数组,第一个[]
定义了内部有三个数组,第二个[]
定义了内部数组的维度,这里只有一维
int[][] jaggedArray = new int[3][];
// 初始化,数组只需维度相同,元素数不定
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[4];
jaggedArray[2] = new int[2];
// 上述定义和下面语句相同
jaggedArray[0] = new int[] { 1, 3, 5, 7, 9 };
jaggedArray[1] = new int[] { 0, 2, 4, 6 };
jaggedArray[2] = new int[] { 11, 22 };
还可以在声明时初始化
// 交错数组new声明的第一个[]不定义数量
// 但是new声明的第二个[]必须定义维度数量
int[][] jaggedArray2 = new int[][]
{
new int[] { 1, 3, 5, 7, 9 },
new int[] { 0, 2, 4, 6 },
new int[] { 11, 22 }
};
// 定义的二维交错数组
int[][,] jaggedArray3 = new int[][,]
{
new int[,] { { 1,2 }, { 3,3 }}
;
也可以不用new来声明:
// 不使用new声明,定义时也需要数组同维度
int[][] jaggedArray4 =
{
new int[] { 1, 3, 5, 7, 9 },
new int[] { 0, 2, 4, 6 },
new int[] { 11, 22 }
};
指定元素数和数组维度定义多维数组的例子
int[][,] jaggedArray5 = new int[3][,]
{
new int[,] { {1,3}, {5,7} },
new int[,] { {0,2}, {4,6}, {8,10} },
new int[,] { {11,22}, {99,88}, {0,9} }
};
使用索引器,其目的是为了访问类中非public的数组类。并且可以自定义访问索引的get
方法和set
方法。索引器可以被定义在类和接口上。
索引器及其参数的类型必须至少具有和索引器相同的可访问性。索引器值不能按引用(作为 ref 或 out 参数)传递。
class Parent
{
string[] s = { "123", "222" };
public string this[int index]
{
get
{
return s[index];
}
set
{
s[index] = value;
}
}
}
void Start()
{
Parent p = new Parent();
Debug.Log(p[1]); // 222
p[1] = "555"; // 输入值默认value
Debug.Log(p[1]); // 555
}
使用索引器,用于访问类中的元素(一般是数组元素,通常通过index访问,但是也可以用于其他需要使用序号的情况,例如使用序号来访问int型中的第n个数字,当然也能访问枚举类型。)。
上述的索引器,可以用=>
设置get和set方法:
class Parent
{
string[] s = { "123", "222" };
public string this[int index]
{
get => s[index];
set => s[index] = value;
}
}
在下例中,使用索引值来访问索引,下面设置的索引器是只读的,实现了通过索引值来访问索引号的方法。
class DayCollection
{
string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
public int this[string day] => FindDayIndex(day);
private int FindDayIndex(string day)
{
for (int j = 0; j < days.Length; j++)
{
if (days[j] == day)
{
return j;
}
}
throw new ArgumentOutOfRangeException(
nameof(day),
$"Day {day} is not supported.\nDay input must be in the form \"Sun\", \"Mon\", etc");
}
}
void Start()
{
DayCollection Days = new DayCollection();
Debug.Log(Days["Sat"]);
}
使用访问器get
和set
方法来定义索引器(以及其他变量)的可读性和可写性。
// Indexer on an interface:
public interface IIndexInterface
{
// Indexer declaration:
int this[int index]
{
get;
set;
}
}
// Implementing the interface.
class IndexerClass : IIndexInterface
{
private int[] arr = new int[100];
public int this[int index] // indexer declaration
{
// The arr object will throw IndexOutOfRange exception.
get => arr[index];
set => arr[index] = value;
}
}
根据上述的例子,接口IIndexInterface
中定义了一个索引器,但是接口本身并无int数组。并且接口中定义了get和set权限,则在继承类中必须实现索引器的get和set。因此索引器的读写权限在接口中已经定义了。
IndexerClass
继承了该接口,并在接口中定义了索引器的读写访问器。
当继承了多个同名索引器的时候,当然也需要使用完全限定名来定义:
string IIndexInterface.this[int index]
{
}