2010-01-06 76 views
11

做一些代碼的閱讀和偶然發現這個片段,我還沒有見過的:它看起來C#索引器的要點或好處是什麼?

public SomeClass { 
    public someInterface this[String strParameter] { 
    get { 
     return SomeInternalMethod(strParameter); 
    } 
    } 
} 

喜歡它被稱爲如下:

SomeClass _someClass = new SomeClass(); 
SomeInterface returnedValue = _someClass["someString"]; 

我有興趣在此功能會適當的還是以這種風格寫作的意圖。例如,爲什麼這會比簡單地調用該函數更受歡迎?

+1

它是自然,優雅,請人看,提高了解。方法調用很無聊。檢查了這一點:http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html – 2010-01-07 01:17:47

回答

19

見語言規範,部分10.9,其中指出:

Indexer是使得以相同的方式作爲數組要索引的對象的構件。

索引器和屬性在概念上非常相似,但不同之處有以下幾種:

  • 屬性是由它的名稱標識,而索引被它的簽名標識。
  • 屬性通過簡單名稱(第7.5節)訪問。2)或成員訪問(第7.5.4節),而索引器元素通過元素訪問(第7.5.6.2節)訪問。
  • 屬性可以是一個靜態成員,而索引器總是一個實例成員。
  • get屬性的訪問器對應於不帶參數的方法,而索引器的get訪問器對應於與索引器具有相同形式參數列表的方法。
  • 屬性的set訪問器對應於具有單個名爲value的參數的方法,而索引器的set訪問器對應於與索引器具有相同形式參數列表的方法,以及名爲value的其他參數。
  • 索引器訪問器聲明與索引器參數具有相同名稱的局部變量是編譯時錯誤。
  • 在重寫屬性聲明中,使用語法base.P訪問繼承的屬性,其中P是屬性名稱。在覆蓋索引器聲明中,使用語法base [E]訪問繼承索引器,其中E是逗號分隔的表達式列表。
+2

我知道我不應該劫持這個,但也許你可以博客爲什麼沒有靜態索引器?當我看到他們不存在時,我感到震驚,僅僅因爲它是一種很好的速記方式。 (在喬恩帶來良好的編碼[「UTF8」]例:) :) – 2010-01-06 22:38:58

+3

我剛剛檢查了設計說明檔案,並沒有任何理由的決定,沒有靜態索引。因此,我必須重新回到我爲什麼沒有特徵的通常解釋:沒有人認爲花這些錢使它變得真實是一個足夠好的主意。我想這同樣的解釋也解釋了爲什麼索引器不能通用。 – 2010-01-06 23:10:17

+0

酷:)關於「默認」解釋的好處是,它並沒有完全關閉這種可能性的大門。我不知道這個功能有多「沉重」(並且我不會因爲不知道編譯器和CLR是如何工作的,而只會說「但它只是一個小小的改變」),但它比「我們沒有做的更好」這是因爲X,Y和Z使得它無法實現「。 – 2010-01-06 23:31:34

5

在很多情況下,'索引'語法很有意義。如果SomeClass表示某種集合,它特別有用。

3

它允許你做關聯數組查找(a.k.a.「dictionary style」),就像你在你的問題中提到的一樣。

而這就是整個觀點。有些人喜歡這樣,特別是來自Python內置語言的人,如Python或PHP

0

它是索引運算符[ ]的實現。

0

這是一個運算符超載。例如,如果您正在編寫集合類,那麼它很有用,例如,使用數組符號訪問它的意義非常重要。集合[someIndex。

你當然可以寫一個collection.GetElement(someIndex)函數等價,但它是一種風格/可讀性的東西。

0

那麼你可以在鍵值對類中使用這種方法。

我不確定c#中類似的類是什麼,但是在C++ STL中,有一個地圖類,在那裏你調用SomeObject["key"]的方法,它將返回與該關鍵字相關聯的「值」。

+0

在C#中的類似的類是System.Collections.Generic.Dictionary (除了字典使用哈希查找,而地圖命令的鍵) – 2010-01-06 22:41:30

0

這就是所謂的索引器,它們允許您使用列表<>,ArrayList,Dictionary <>和所有使用數組語法的其他集合。

這只是語法糖,但它使用正確時會提供一些可讀性。

1

您可能已經偶然發現了類似的事情之前:

var myList = new List<string>(); 
myList.Add("One"); 
myList.Add("Two"); 
myList.Add("Three"); 

for(int i = 0; i < myList.Count; i++) { 
    string s = myList[i]; 
} 

的索引是實現集合對象的「主鍵」。如果你想要的話,它只是寫一個像.GetValue(索引)這樣的函數的簡寫方法 - 語法糖。但這也意味着明確。

13

看起來很多答案都是關注索引器的功能,而不是你爲什麼要使用索引器。

就我而言,這裏是使用一個索引的動機:

您是在一類一個某種形式的收集工作,但你想要的類來呈現給用戶(該類消費者)好像它的一個集合。

我能想到的最好的例子是ADO.NET中的DataRow類。如果要獲取DataRow的第五個單元格的值,則可以使用DataRow.Item[4]DataRow[4]。後一種形式是一種方便而合乎邏輯的捷徑,它很好地展示了你爲什麼要使用索引器。對用戶來說,DataRow可以被認爲只是一個單元集合(儘管它實際上不止於此),所以能夠直接獲取和設置單元格值是有意義的,而不必記住自己實際上是實際的獲得/設置Item

希望有所幫助。

0

在我看來,這只是一種語法方便。 會在哪裏,你使用它:

public SomeClass { 
    private int[] nums; 
    public GetVal this[int ind] { 
    get { 
     return nums[ind]; // this is pointless since array is already indexed 
    } 
    } 
} 

會在哪裏,你從中受益

public Matrix { 
    private Dictionary<string, double> matrixData; // Matrix indecies, value 
    public double this[int row, int col] { 
    get { 
     return matrixData[string.Format("{0},{1}", row, col)]; 
    } 
    } 
} 

正如你所看到的,由於某種原因,你的數據是一個索引的字典字符串鍵,並且您希望用兩個整數indecies調用它,但仍不想更改您的數據類型:

Matrix m = new Matrix(); 
... 
Console.WriteLine(m[1,2]);