上一篇結尾的時候我留下了幾個問題,因為要斷電了沒有解決,這一篇我們繼續上一篇的內容。點這裡回到上一篇
數組有多維度的,索引器也可以是多維的嗎???
索引器可以是多維的,上一篇中我們定義的索引器只是一維索引器,同數組一樣可以定義多維索引器。比如我們索引電影院的一個放映室的座位號,第一排第一列為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)+號);
}
}
}
}
結果:
