索引器允許類或結構的執行個體就像數組一樣進行索引。索引器類似於屬性,不同之處在於它們的訪問器採用參數。
在下面的樣本中,定義了一個泛型類,並為其提供了簡單的 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;
}
}
}
// This class shows how client code uses the indexer
class Program
{
static void Main(string[] args)
{
SampleCollection<string> stringCollection = new SampleCollection<string>();
stringCollection[0] = "Hello, World";
System.Console.WriteLine(stringCollection[0]);
}
}
索引器概述
this,類的索引器:
下面的樣本說明如何聲明私人數組欄位、temps 和索引器。使用索引器可直接存取執行個體 tempRecord[i]。另一種使用索引器的方法是將數組聲明為 public 成員並直接存取它的成員 tempRecord.temps[i]。
請注意,當計算索引器的訪問時(例如,在 Console.Write 語句中),將調用 get 訪問器。因此,如果 get 訪問器不存在,將發生編譯時間錯誤。
代碼
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
// To enable client code to validate input
// when accessing your indexer.
public int Length
{
get { return temps.Length; }
}
// Indexer declaration.
// If index is out of range, the temps array will throw the exception.
public float this[int index]
{
get
{
return temps[index];
}
set
{
temps[index] = value;
}
}
}
class MainClass
{
static void Main()
{
TempRecord tempRecord = new TempRecord();
// Use the indexer's set accessor
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
// Use the indexer's get accessor
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
使用其他值進行索引
C# 並不將索引類型限制為整數。例如,對索引器使用字串可能是有用的。通過搜尋集合內的字串並返回相應的值,可以實現此類索引器。由於訪問器可被重載,字串和整數版本可以共存。
樣本 2
說明
在此例中,聲明了儲存星期幾的類。聲明了一個 get 訪問器,它接受字串(天名稱),並返回相應的整數。例如,星期日將返回 0,星期一將返回 1,等等。
代碼
// Using a string as an indexer value
class DayCollection
{
string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
// This method finds the day or returns -1
private int GetDay(string testDay)
{
for(int j = 0; j < days.Length - 1; j++)
{
if (days[j] == testDay)
{
return j;
}
}
throw new System.ArgumentOutOfRangeException(testDay, "testDay must be in the form \"Sun\", \"Mon\", etc");
}
// The get accessor returns an integer for a given string
public int this[string day]
{
get
{
return (GetDay(day));
}
}
}
class Program
{
static void Main(string[] args)
{
DayCollection week = new DayCollection();
System.Console.WriteLine(week["Fri"]);
// Raises ArgumentOutOfRangeException
System.Console.WriteLine(week["Made-up Day"]);
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
// Output: 5
可靠編程
提高索引器的安全性和可靠性有兩種主要的方法:
-
確保結合某一類型的錯誤處理策略,以處理萬一用戶端代碼傳入無效索引值的情況。在本主題前面的第一個樣本中,TempRecord 類提供了 Length 屬性,使用戶端代碼能夠在將輸入傳遞給索引器之前對其進行驗證。也可以將錯誤處理代碼放入索引器自身內部。確保為使用者記錄在索引器的訪問器中引發的任何異常。有關更多資訊,請參見異常設計準則。
-
應當為 get 和 set 訪問器的可訪問性設定儘可能多的限制。這一點對 set 訪問器尤為重要。有關更多資訊,請參見 非對稱訪問器可訪問性(C# 編程指南)。
屬性和索引器之間的比較:
索引器與屬性類似。除下表中顯示的差別外,為屬性訪問器定義的所有規則同樣適用於索引器訪問器。
|
屬性 |
索引器 |
|
允許像調用公用資料成員一樣調用方法。 |
允許對一個對象本身使用數組標記法來訪問該對象內部集合中的元素。 |
|
可通過簡單的名稱進行訪問。 |
可通過索引器進行訪問。 |
|
可以為靜態成員或執行個體成員。 |
必須為執行個體成員。 |
|
屬性的 get 訪問器沒有參數。 |
索引器的 get 訪問器具有與索引器相同的形參表。 |
|
屬性的 set 訪問器包含隱式 value 參數。 |
除了值參數外,索引器的 set 訪問器還具有與索引器相同的形參表。 |
|
支援對自動實作屬性(C# 編程指南)使用短文法。 |
不支援短文法。 |