2012-03-19 18 views
4

我一直看到列表派生類是這個樣子爲什麼要派生一個List <T>類才能重申一個索引器?

class MyClassList : List<MyClass> 
{ 
    public MyClass this[int index] 
    { 
     get { return (MyClass)base[index]; } 
    } 
} 

這是什麼傳承的意義呢?它看起來只是重申了成員的投射。我可以理解其他類型的索引器,但這只是對默認List索引器的重述,並引發了Visual Studio警告RE:隱藏了基本索引器。這是正確還是錯誤的事情?爲什麼?

+3

我不知道你在哪裏看到這樣的代碼,但有數百萬的事情只是顯然不對! – leppie 2012-03-19 15:28:43

+2

你在哪裏看到?因爲我從來沒有見過它。這是一段可怕的代碼。 – flq 2012-03-19 15:29:04

+4

猜測:Newb編碼器試圖隱藏setter。 (大聲笑) – leppie 2012-03-19 15:29:28

回答

2

這沒有什麼好的理由。它隱藏基礎索引器而不是覆蓋它,這可能是危險的,它根本沒有任何影響。

在大多數情況下,最好直接使用使用 a List<MyClass>。如果您不打算擴展List<>的功能,則無需爲此創建專門的課程。

+0

好的,後續的 - 如果一個*擴展了基數,我認爲基數索引器應該保持單獨,正確嗎? – downwitch 2012-03-19 15:47:08

+0

@downwitch:是的,除非有特定的理由這麼做。例如,您可能希望在收集更改時觸發事件。在這種情況下,你會*覆蓋*(不隱藏)基礎索引器,導致它調用基礎索引器,然後觸發適當的事件。或者您可能會決定在設置了特定標誌後,不允許進行更改:在這種情況下,如果設置了該標誌,則會覆蓋基礎索引器以引發異常。覆蓋索引器有合理的理由。隱藏它的原因要少得多。在這種情況下,兩者都不適用。 – StriplingWarrior 2012-03-19 16:16:51

0

我已經看到過這種類型的東西之前,人們想要序列化出來作爲另一種類型,現在,如果這是唯一的代碼在那裏,並不需要爲其他原因類型MyClassList,它完全沒有意義。

1

我沒有看到這樣做的任何用處。 此外,演員陣容是不必要的。

0

這個,基本上,一個嘗試做出正確凌駕於[]訪問List,以實現一些自定義的元素訪問邏輯。

值得提的是,提供的代碼不好,如果不是隻有危險。如果你想用列表做一些棘手的事情,請不要覆蓋(或傾向於這樣做)[],但實現一些用於此目的的自定義方法。

5

也許這是一個很差試圖防止通過索引器覆蓋值?

MyClassList x = new MyClassList(); 
x.Add(new MyClass()); 
x[0] = new MyClass(); // Error! 

當然,它不會停止這樣的:

List<MyClass> x = new MyClassList(); 
x.Add(new MyClass()); 
x[0] = new MyClass(); // No problem here... 

基本上,這是一個壞主意。不幸的是,不好的代碼很多 - 從單純的存在並不能推斷出有用性:(

1

我認爲它應該隱藏基類的set訪問器,使其看起來像索引器是隻讀的。 ,因爲它是很容易解決:

MyClassList list = ... 

((List<MyClass>)list)[index] = value; 

反正List<T>類不適合繼承如果你需要創建一個專門收集,從Collection<T>而不是繼承

+0

我發現你最後的陳述有點混亂。不是基於* any *類是爲繼承而設計的想法的多態性?在我看來,List 的開箱即用方法的數量和相對易用性使其成爲更快建立的基類。我錯過了什麼? – downwitch 2012-03-19 16:20:40

+0

你缺少的是'List '類中的方法都不是虛擬的,這使得覆蓋它們成爲不可能的。你總是可以隱藏它們,但它是一個完全不同的概念......隱藏基類定義的方法不會參與多態。 – 2012-03-19 16:23:19

+0

事實上,這是非常有道理的,就我所讀過的主題而言,我記得沒有人會打擾說明這個簡單的說法:*如果一個類是爲繼承而設計的,那麼它的方法就是虛擬*。也許很明顯,但對我來說不是。 – downwitch 2012-03-19 17:03:56

0

我的猜測。該代碼試圖表現爲只讀List。其中之一是無法通過索引寫入MyClassList<T>類型的變量的項目,儘管有人將能夠將它轉換回List<T>寫一個變量的方式。有些時候,如果有一個變量的類型能力有限,可以容納一個實際能力更大的對象。儘管如此,正確的方法通常是使用接口,最主要的例子是IEnumerable<T>。如果List<T>傳遞給接受類型爲IEnumerable<T>的參數的例程,則該例程可將其參數重新轉換爲List<T>,並使用Add(),Remove()等成員,但必須接受類型爲IEnumerable<T>的參數的例程不會嘗試將它用作其他任何東西。

原始海報顯示的代碼風格的一個主要問題是更強大的方向是基礎,而不是派生類型。因爲List<T>派生自IEnumerable<T>,這意味着所有List<T>的實例都可以枚舉,但不僅如此,有些枚舉的事物在List<T>中有額外的功能。相比之下,隨着班級的實施,每個MyClassList<T>都可以讀取和寫入,但只有List<T>的某些實例可以用作MyClassList<T>

相關問題