上一篇結尾的時候我留下了幾個問題,因為要斷電了沒有解決,這一篇我們繼續上一篇的內容。點這裡回到上一篇
數組有多維度的,索引器也可以是多維的嗎???
索引器可以是多維的,上一篇中我們定義的索引器只是一維索引器,同數組一樣可以定義多維索引器。比如我們索引電影院的一個放映室的座位號,第一排第一列為1號,一排2列為2號……如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test1 {//定義cinema類包含一個二維數組與一個二維訪問器 class cinema {//定義一個二維數組 private string[,] seat = new string[5, 5]; //定義一個二維訪問器 public string this[uint a, uint b] { get { return seat[a, b]; } set { seat[a, b] = value; } } } class Program { static void Main(string[] args) { cinema movieroom = new cinema();//實例化 //for循環遍歷寫入 for (uint i = 1; i < 5; i++) { for (uint j = 1; j < 5; j++) { movieroom[i, j] = 第 + i + 排 第 + j + 列; } } //for循環遍歷讀出 for (uint i = 1; i < 5; i++) { for (uint j = 1; j < 5; j++) { Console.WriteLine(movieroom[i,j]+ +((i-1)*4+j)+號); } } } } }
結果:
二維的索引器就是如此了,其他多維數的都以此類推,就不介紹了。
數組能夠使用foreach語句進行簡單快捷的遍歷,索引器也能使用foreach語句遍歷麼???
這個也是可以的,在解決這個問題的時候有必要弄清楚foreach的執行步驟與原理.
C#中編譯器會把foreach語句轉化為IEnumerable接口的方法和屬性,比如:
string[] str = new string[] { HC1, HC2, HC3, HC4 };//定義一個數組 foreach (string i in str)//使用foreach遍歷 { Console.WriteLine(i); }
然而foreach語句會被解析為下面的代碼段。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; //注意添加這個命名空間,否則沒有IEnumerator這個類 namespace Example { class Program { static void Main(string[] args) { string[] str = new string[] {HC1,HC2,HC3,HC4 }; //定義一個數組 //調用GetEnumerator()方法,獲得數組的一個枚舉 IEnumerator per = str.GetEnumerator(); //在while循環中,只要MoveNext()返回true,就一直循環下去 while (per.MoveNext()) { //用Current屬性訪問數組中的元素 string p = (string)per.Current; Console.WriteLine(p); } } } }
結果都一樣:
我們對string查看定義發現,string繼承於IEnumerable接口,IEnumerable接口中只有一個方法GetEnumerator();(該方法已在string類中被實現了)該方法的作用是,返回一個循環訪問集合的枚舉器IEnumerator,我們在轉IEnumerator的定義,它也是一個接口,裡面只有三個方法的聲明,Current(獲取集合中的當前元素),MoveNext(將枚舉數推進到集合的下一個元素,成功返回true,越過結尾返回false),Reset( 將枚舉數設置為其初始位置,該位置位於集合中第一個元素之前),也就是說,如果在我們自定義的類中沒有實現GetEnumerator方法,以及Current、MoveNext方法,就不能使用foreach語句遍歷了。
還是上面電影院的例子,不過這次我們不用for循環輸出,而是實現foreach語句遍歷輸出,如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; //添加這個很有必要 namespace Test1 {//定義cinema繼承IEnumerable接口實現GetEnumerator()功能 class cinema:IEnumerable {//定義一個二維數組 private string[,] seat = new string[5, 5]; //定義座位號碼 static public int index=-1; //定義一個二維索引器 public string this[uint a, uint b] { get { return seat[a, b]; } set { seat[a, b] = value; }//set訪問器自帶value參數 } //實現GetEnumerator方法 public IEnumerator GetEnumerator() { return new ienumerator(seat); //利用構造方法傳入seat參數 } //由於上面返回值的需要所以繼承接口IEnumerator並實現方法 private class ienumerator:IEnumerator { private string[,] seats; //將傳入的seat數組賦給它 public ienumerator(string[,] s) { seats = s; } //定義Current的只讀屬性 public object Current { //根據座位號推算數組的坐標也就是物理位置 get { return seats[1+(index/4), (index%4)+1]; } } //定義向下移動的規則 public bool MoveNext() { index++; //索引下一個座位號的位置 if (index <= 15) { return true; } else return false; } //因為這個程序中用不到這個方法所以不實現,但是必須得寫上否則會報錯 public void Reset() { } } } class Program { static void Main(string[] args) { cinema movieroom = new cinema();//實例化 //for循環索引寫入 for (uint i = 1; i < 5; i++) { for (uint j = 1; j < 5; j++) { movieroom[i, j] = 第 + i + 排 第 + j + 列; } } //調用foreach語句遍歷輸出 foreach (string i in movieroom) { Console.WriteLine(i+ +(cinema.index+1)+號); } } } }
結果: