C#中的索引子
(Indexer)是一個相當直覺好用的設計,讓開發者可以在建立類別時,如同存取陣列一樣的對內部資料做存取,用來封裝內部集合或陣列。
索引子 (Indexer) 允許使用與陣列相同的方式來索引類別 (Class) 或結構 (Struct) 的執行個體。 索引子除了其存取子 (Accessor) 會使用參數以外,其餘特性都與屬性相似。
在下列範例中,將定義一個泛型類別,並提供簡單的 get 與 set 存取子方法來做為指派與擷取值的方式。 Program 類別會建立此類別的執行個體以儲存字串。
class SampleCollection<T>
{
private T[]
arr = new T[100];
public T this[int i]
{
get
{
return arr[i];
}
set
{
arr[i] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
SampleCollection<string>
stringCollection = new SampleCollection<string>();
stringCollection[0] = "Hello,
Indexer";
System.Console.WriteLine(stringCollection[0]);
}
}
索引子概觀
- 索引子可讓物件以類似於陣列的方式進行索引。
- get 存取子會傳回一個值。 set 存取子會指定一個值。
- this 關鍵字的用途為定義索引子。
- value 關鍵字是用來定義 set 索引子所指定的值。
- 索引子不需要以整數值來索引;您可以決定如何定義特定的查詢機制。
- 索引子可以多載。
- 索引子可以具有一個以上的型式參數,例如,在存取二維陣列時便是如此。
例如有10個村里要發佈成為土石流警戒區,希望將這些村里歸類到所屬的鄉鎮,以方便可以快速的取出鄉鎮及村里統計及詳細資訊,最重要的是希望用一種更直覺的方式來實現這樣的設計。
實作方法設計 County 和 Town 兩個類別:
在 County 中使用 Indexer,使用者可以指定鄉鎮就可以存取內部的鄉鎮清單(TownItem),在 get及set存取運算子中,使用
Lambda 來判斷鄉鎮是否存在 TownItem 內:
public class County
{
public string Name{set;get;}// 縣市名稱
private List
TownItem = new List();// 鄉鎮清單
//鄉鎮名稱
public Town this[String
town]
{
get
{
//透過 Lambda 判斷鄉鎮是否存在 TownItem內
Town pTown
= this.TownItem.Find(c => (c.Name == town));
if (pTown == null)
{
TownItem.Add(new Town() { Name = town });
pTown = this.TownItem.Find(c => (c.Name == town));
}
return pTown;
}
set
{
Town pTown
= this.TownItem.Find(c => (c.Name == town));
if (pTown == null)
{
TownItem.Add(new Town() { Name = town });
pTown = this.TownItem.Find(c => (c.Name == town));
}
pTown = value;
}
}
}
Town 類別就只是一個單純的資料類別,負責用來記錄資料
public class Town
{
public String
Name { set; get; }
private List
VillItems = new List();
public void AddVill(String
VillName)
{
VillItems.Add(VillName);
}
public List
Items
{
get { return this.VillItems;}//取回村里清單
}
}
使用Indexer的方式,就如同下面的範例:
County pCounty = new County()
{ Name = "台中市" };
//分別加入幾個村里到行政區內
pCounty["西屯區"].AddVill("至善里");
pCounty["西屯區"].AddVill("逢甲里");
pCounty["北屯區"].AddVill("北屯里");
pCounty["北屯區"].AddVill("三合里");
//取出在西屯區的村里資料
foreach (String s in pCounty["西屯區"].Items)
{
Console.WriteLine(s);
}
這跟array 很像但是不同的是他可以透過string 的方式去找尋某集合的個體,每一個縣市都是被封裝起來,等需要時,再透過string索引出來使用。
下面是一個搜尋使用者的類別方法:
public class User
{
private List<string>
AllUser { get; set; }//所有User
public User(int num)//Ctor
{
AllUser
= new List<string>();//Init
//使用者放入多少數字我就建立多少資料進入AllUser
for (int i =
0; i <= num; i++)
{
AllUser.Add("使用者" +
i);
}
}
//Indexer 數字
public string this[int index]
{
get
{
if (index < AllUser.Count)
{
return AllUser[index];
}
else
{
return "Error";
}
}
set
{
AllUser[index] = value;
}
}
//Indexer Overloading 文字
public string this[string indexValue]
{
get
{
foreach (var user in AllUser)
{
if (user == indexValue)
{
return AllUser.IndexOf(user).ToString();
}
}
return "No User";
}
}
}
在範例中AllUser被封裝起來,但允許使用者透過indexer 透過數字去找尋AllUser
輸入文字之後,就會回覆該User所在位置。它的概念很像Json的存取方式,但又結合了Array對每個位址記憶的存放,非常的方便。
-雲遊山水為知已逍遙一生而忘齡- 電腦神手