数 组
所有数组类型都隐式地从System.Array抽象类派生,后者又派生自System.Object。这意味着数组是在托管堆上进行分配的。
对于0基数组,Microsoft花了大量的时间来优化它们的性能,而且0基数组符合CLS(公共语言规范here),所以它将支持跨语言移植,如可用C#创建一个数组,然后将该数组的引用传给另一种语言写的代码。
从上图中可以看到,每个数组都关联了一些额外的开销信息(Overhead),在这些信息中包括数组的维数、数组的每一维的下限、每一维的长度、数组的元素类型。
数组初始化器:
string[] names = new string[]{"bill","gates"};
大括号和其中的以逗号分隔的数据项称为数组初始化器。每个数据项都可以是一个任意复杂度的表达式;在多维数组的情况下,则可以是一个嵌套的数组初始化器。在上例中,我只是使用了两个简单的string表达式。
利用C#的隐式类型的局部变量功能:
var names = new string[]{"bill","gates"};
利用C#的隐式类型的局部变量功能和隐式类型的数组功能:
var names = new[]{"bill","gates",null};
更简单的初始化数组的方法:
string[] names = {"bill","gates"};
Array.Copy(源数组,目标数组,要拷贝的元素个数)
它是一个浅拷贝,换句话说,如果数组元素是值类型或字符串类型的话,相当于深拷贝,无论是对源数组还是对目标数组进行操作,他们不会彼此受影响。 如果数组元素是引用类型的话,无论是对源数组还是对目标数组进行操作,他们之间是相互影响的,相当于只拷贝了引用类型的引用。
namespace WebApplication1 { public class people { public string name; } public partial class ArrayCopy : System.Web.UI.Page { int[] int1 = { 1, 2, 3, 4, 5, 6 }; int[] int2 = new int[6]; people[] people1 = new people[2]; people[] people2 = new people[2]; protected void Page_Load(object sender, EventArgs e) { Array.Copy(int1, int2, int1.Length); foreach (var item in int1) { Label1.Text += item.ToString(); //123456 } people p1 = new people(); people p2 = new people(); p1.name = "A"; p2.name = "B"; people1[0] = p1; people1[1] = p2; Array.Copy(people1, people2, people1.Length); foreach (var item in people1) { Label4.Text += item.name; //AB } } protected void Button1_Click(object sender, EventArgs e) { int2[0] = 2; int2[1] = 3; int2[2] = 4; int2[3] = 5; int2[4] = 6; int2[5] = 7; foreach (var item in int1) { Label2.Text += item.ToString(); //123456 } foreach (var item in int2) { Label3.Text += item.ToString(); //234567 } } protected void Button2_Click(object sender, EventArgs e) { people2[0].name = "B"; people2[1].name = "A"; foreach (var item in people1) { Label5.Text += item.name; //BA } foreach (var item in people2) { Label6.Text += item.name; //BA } } } }
所有数组都隐式派生自System.Array
如果声明一下数组:
string[] strs;
CLR会自动为AppDomain自动创建一个string[]类型。这个类型隐式派生自System.Array,因此,System.Array类型定义的所有实例方法和属性都将由string[]继承,这些方法和属性都能由strs变量调用。比如:Clone、CopyTo、GetLowerBound、Length、Rank等。
System.Array开有许多用于处理数组的静态方法,这些方法均获取一个数组引用作为参数。比如:AsReadOnly、BinarySearch、Clear、ConstrainedCopy、ConvertAll、Copy、Exists、Find、FindAll、FindIndex、FindLast、FindLastIndex、ForEach、IndexOf、LastIndexOf、Resize、Reverse、Sort、TrueForAll等。
所有数组都隐式实现IEnumerable、ICollection、IList
许多方法都能操作各种集合对象,因为在声明它们时使用了IEnumerable、ICollection、IList等参数。由于System.Array也实现了这三个接口,所以可以将数组传给这些方法。
这里要提到的一点是由于涉及到多维数组及非0基数组的原因,System.Array并没有实现IEnumerable<T>、ICollection<T>、IList<T>这些泛型类,但
当声明 一维0基引用类型数组 时,CLR会自动使该数组实现IEnumerable<T>、ICollection<T>、IList<T>这些泛型类,并且还会为该引用类型的所有父类数组都实现这些泛型类
而声明 一维0基值类型数组 时,CLR只会自动使该数组实现IEnumerable<T>、ICollection<T>、IList<T>这些泛型类,而不会为该值类型的所有父类数组都实现这些泛型类
创建非0基数组
可以通过 Array.CreatInstance(数组元素类型,每一维的元素个数,每一维的下限) 来创建下限非0的数组。如果数组的维数是2或2个以上,则可以使用像普通数组一样方来访问或设置数组元素,如果数组只有一维,C#中只能通过Array的GetValue和SetValue来访问数组元素,而不能通过强制转换的方式把Array转换成一维数组。
//下限是20长度是2的一维数组 protected void Button3_Click(object sender, EventArgs e) { Array a= Array.CreateInstance(typeof(int), new int[] { 2 }, new int[] { 20 }); a.SetValue(1, 20); a.SetValue(2, 21); foreach (var item in a) { Label7.Text += item.ToString(); } Label7.Text += a.GetValue(20); //121 } //第一维下限是4长度是2第二维下限是5长度是3的二维数组 protected void Button4_Click(object sender, EventArgs e) { int[,] a = (int[,])Array.CreateInstance(typeof(int), new int[] { 2, 3 }, new int[] { 4, 5 }); a[4, 5] = 20; a[4, 6] = 21; a[4, 7] = 22; a[5, 5] = 23; a[5, 6] = 24; a[5, 7] = 25; foreach (var item in a) { Label8.Text += item.ToString(); } Label8.Text += a[5, 5].ToString(); //20212223242523 }
多维数组与交错数组,lookhere