如果需要使用同一類型的多個對象,就可以使用集合和數組,c#使用特殊句號聲明和初始化數組,簡單來說需要時使用同一類型的多個對象時,就可以使用數組,數組是一種數據結構。
數組的聲明:
int[] Array;
數組的初始化:
聲明數組後必須給數組分配內存,以保存數組的所有元素,數組是引用類型,所以必須給他分配堆上內存,因此使用new運算符。 數組聲明的的方式。
int[] Array=new int[];
初始化的三種方式:
int[] Array=new int[4]{1,2,3,4};
int[] Array=new int[]{1,2,3,4};
int[] Array={1,2,3,4};
在聲明和初始化數組後就可以使用索引器訪問數組的元素了,數組只支持有整型參數的索引器,通過索引便可以訪問其中的元素(從0開始)。
int[] Array={1,2,3,4};
Array[0]=1, Array[3]=4;
如果不知道數組的元素個數可以用Length屬性,下面兩種也是取數據的方式
for(int i=0;i<Array.length;i++)
{
int a=Array[i];
}
foreach(int b in Array)
{
int a=b;
}
引用類型數組
除了能聲明預定義類型的數組外,還可以聲明自定義類型數組
public class Person
{
public string FirstName;
public string LastName;
}
數組聲明:
person[] Array=new person[2];
數組初始化::
和int類型一樣。
person[] Array=new person[2]{new person{FirstName="大衛",LastName="菠蘿"},new person{FirstName="小衛",LastName=“土豆”}};
其實引用類型的數組和int類型數組一樣,只不過把類型換了一下而已。
多維數組
一般數組(一維數組)用一個整數來索引,多維用兩個或者多個整數來索引。
二維數組聲明
int[,] Array=new int[2,3](代表2行3列的數組)。
二維數組初始化
int[,] Array=new int[]{{1,2},{1,3},{1,4}}//(代表3行2列的數組)。
//取值,索引從0開始
Array[0,0]=1;
Array[0,1]=2;
3維數組及以上,還有鋸齒數組都差不多,就不討論了。
Array類
用方括號聲明數組是c#中使用Array類的表示法,在後臺使用c#語法,會創建一個派生自抽象基類Array的新類,這樣就可以使用Array爲每個c#數組定義的方法和屬性了,,例如前面使用的Length屬性,或者是foreach語句來迭代數組,其實使用了Array類中的GetEnumerator()方法。(我的理解就是數組可以使用Array類中的屬性和方法).
Array類實現的其他屬性有longlength和rank,longlength表示所有維數中元素的個數,rank表示維數。
Array類是抽象類,所以不能構造函數來創造數組,但是可以用靜態方法來CreateInstance()方法來創建數組,如果事先不知道元素類型就很有用,因爲類型可以當做參數傳進去。
//創建一個類型爲int,大小爲5的數組
Array IntArray=Array.CreateInstance(typeof(int),5);
//賦值
for(int i=0;i<IntArray.length;i++)
{
IntArray.SetValue(33,i);//後面i爲索引
}
//取值
for(int i=0;i<IntArray.length;i++)
{
int a= IntArray.GetValue(i);
}
引用數組,鋸齒數據,多維數組同樣可以用Array.CrueateInstance方法來創建,則不再討論。
複製數組
因爲數組是引用類型,所以將一個數組賦值爲另外一個數組,就會等到兩個引用同一數組的變量,複製數組會實現ICloneable接口,這個接口定義的Clone()方法會創建數組的淺表副本(我的理解就是 數組 a=數組 b 改變數組a的值,b也會跟着改變,數組 a=數組b.clone()改變a的值不會改變b的值)
排序
Array類使用QuickSort算法對數組中的元素進行排序,Sort()方法需要數組中元素實現Icomparable接口
int[] Array={3,2,1};
Array.sort(Array);
//從小到大排序,則Array裏數據排序
Array[0]=1;
Array[1]=2;
Array[2]=2;
引用類型數組排序就不在這裏介紹了,沒有封裝好的方法,需要自己寫。
數組作爲參數
int[] Array={1,2,3};
static void TestArray(int[] pram)
{
//....... 函數體
}
//數組協邊,即數組也可以聲明爲基類(通俗點就是object[] 可以傳數組)
static void TestArray(object[] pram)//可以傳引用類型的數組
{
//....... 函數體
}
數組協變,只能用於引用類型,不能用於值類型,數組協邊有個問題,他只能通過運行時異常來解決,如果把引用數組賦予object[]數組,object數組就可以使用使用派生自object的任何元素。(不建議用object[])。
ArraySegment<T>
結構ArraySegment<T>表示數組的一段,如果需要使用不同的方法處理某個大型方法的不同部分,則需要將相應的部分傳到相應的方法中,更有效的是使用一個數組,將整個數組傳遞到不同方法去。
//舉個簡單的例子,若有兩個不同的數組,選取不同的部分求和,則可以使用Arraysegment
static int SumOfSegment(Arrsegement<int>[] segments)
{
int sum=0;
foreach(var segment in segments)
{
for(int=segment.offest;i<segment.offset+segment.count;i++)
{
sum+=segment.array[i];
}
}
return sum;
}
int[] a={1,2,3,4,5};
int[] b={2,3,4,5,6,7};
//數組a取出索引1,往後數兩個數的數(從索引開始算),數組b,取出索引1,往後數3個數的數(從1開始算),a 取出2,3,b取出3,4,5
static void TestSegMent()
{
ArraySegment<int>[] segments=new ArraySegment<int>[2]{new ArraySegment<int>(a,1,2),new ArraySegment<int>(b,1,3)};//將不同數組的不同部分傳入segment中(自我感覺不咋用的到0.0)
int sum=SumOfSegment(segments);
}
枚舉
在foreach語句中使用枚舉,可以迭代集合中元素,無須知道集合的個數,foreach使用了一個枚舉器。;數組或集合實現帶GetEumerator()方法的IEnumerable接口。
Tip:GetEnumerator()方法用IEnumerable接口定義,foreach語句並不真的需要在集合類中實現這個接口,有一個名爲GetEnumerator的方法,他返回了實現IEnumerator接口的對象就足夠了。
IEnumerator接口
foreach語句使用IEnumerator接口的方法和屬性,迭代集合中所有的元素,爲此IEnumerator定義了current屬性,來返回光標當前所在的元素。該接口的MoveNext()方法移動到集合的下一個元素,如果有這個元素就返回true,如果沒有下一個元素則返回false.該接口的泛型版本IEnumerator<T> 接口派生自IDisposable接口,因此定義了Dispose()方法,來清理枚舉器產生的資源。
Foreach語句
int[] array={1,2,3,4};
foreach(int a in array)
{
console,writeline(a)
}
//上面的foreach等價於下面的枚舉器
IEnumeator<int> enumerator=array.GetEnumerator()//用getenumerator()方法獲得數組的一個枚舉器
while(enumerator.movenext())
{
int p=enumerator.current;
console.writeline(p);
}
Yield語句
c#2.0添加了yield語句,以便於創建枚舉器,yield return語句返回集合的一個元素,並移動到下一個元素上,yield back可以停止迭代。
//返回hello world
pubic IEnumerator<string> GetEnumerator()
{
yield return "Hello";
yield return "wrold";
}
tip:包含yeild語句的方法和屬性也被成爲迭代塊,迭代塊必須聲明爲返回IEnumerator或者IEnumerable接口,或者這些接口的泛型版本。這個快可以包含多個yeild return和yeild back語句,但是不能包含return語句.
元組
元組的初始化
//元組初始化時應設值否則會報錯
Tuple<int,string> tuple=new Tuple<int,string>(1,"2");
//或者下一種
Tuple<int,string> tuple=new Tuple<int,string>(1,"2");
數組是和並相同類型的成員,元組是合併不同類型的成員。,net定義了8個泛型的Tuple類和一個靜態Tuple類,例如Tuple<T1>包含一個元素,Tuple<T1,T2>包含了兩個元素。
public Static Tuple<int,string> Divide(int a,int b)
{
int result1=a+b;
int result=(a-b).tostring();
return Tuple.Create<int,int>(result1,reult2);
}
public static Test()
{
Tuple<int,string> tuple= Divide();
int a=tuple.item1;//第一個數
string b=tuple.item2;//第二個數
}
Tip:如果元祖包含的項超過8個,就可以用帶8個參數的Tuple類定義,最後一個模板參數是TRest表示必須給它傳遞一個元組,舉個例子
//當元組包含的項超過8個時,最後一個模板必須是元組
var tuple = new Tuple<int, int, int, int, int, int, int, Tuple<int, string>>(1, 1, 1, 1, 1, 1, 1, Tuple.Create<int, string>(1, "2"));
//或者下一種
var tuple2 = new Tuple<int, int, int, int, int, int, int, Tuple<int, string>>(1, 1, 1, 1, 1, 1, 1, new Tuple<int, string>(1,"2"));
(自我感覺元組的使用就是當類中的元素少的時候,可以用元組替代,簡化代碼)。