2009-09-11 36 views
11

有了這個代碼...有什麼魔力約ReadOnlyCollection

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 }); 
b[2] = 3; 

我在第二條線得到一個編譯錯誤。我期望運行時錯誤,因爲ReadOnlyCollection<T> implements IList<T>this[T]IList<T>接口中有一個setter。

我試着複製ReadOnlyCollection的功能,但是從this[T]刪除setter是一個編譯錯誤。

回答

16

indexer與明確的實施接口的實現,所以你只能將能夠訪問它,如果你這樣做:

IList<int> b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 }); 
b[2] = 3; 

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 }); 
((IList<int>)b)[2] = 3; 

當然,它會失敗,然後在執行時...

這完全是蓄意的,有幫助的 - 這意味着,當編譯器知道這是一個ReadOnlyCollection,功能不支持位是不可用對你有幫助,可以讓你遠離執行時間的失敗。

雖然這是一個有趣且相對不尋常的步驟,但實際上隱式地實現了屬性/索引器的一半,明確地實現了一半屬性/索引器。

相反,我以前的想法,我相信ReadOnlyCollection<T>實際上明確地實現了整個索引,但提供公共只讀索引。換句話說,它是這樣的:

T IList<T>.this[int index] 
{ 
    // Delegate interface implementation to "normal" implementation 
    get { return this[index]; } 
    set { throw new NotSupportedException("Collection is read-only."); } 
} 

public T this[int index] 
{ 
    get { return ...; } 
} 
+0

好的,但我如何使用顯式實現複製ReadOnlyCollection的功能。我看不出如何從界面中刪除方法或屬性。 – 2009-09-11 09:47:04

+0

@EsbenP:你不能從接口中移除一個方法......但是你可以只在引用的靜態類型是接口而不是實現接口的類時纔可用。 – 2009-09-11 10:14:42

+0

好吧,如果我有兩個索引,他們實施的IList的一個明確它的工作原理 牛逼的IList 。這[INT指數] { 得到 { 返回源[指數] } set { throw new NotImplementedException(); } } 公共Ť此[INT指數] { 得到 { 返回源[指數]; } } – 2009-09-11 10:23:12

2

它明確地實現了IList.Items,這使得它是非公開的,你必須轉換到接口來實現它,並實現一個新的索引器,它只有一個get-accessor。

如果您將集合轉換爲IList,您的代碼將會編譯,但在運行時會失敗。

不幸的是,我不知道如何做到這一點在C#中,因爲在C#編寫索引使用this關鍵字涉及的,你不能這樣寫:

T IList<T>.this[int index] { get; set; } 
+0

@Lasse:您可以編寫 - 適當的實現。據我所知,問題在於你無法明確地半明確地執行一半。 – 2009-09-11 10:21:01

+0

如果你可以寫這個,你不需要,只要拋出一個異常就可以編寫setter,然後用getter實現一個public [..]索引器。 – 2009-09-11 11:05:49

1

沒有魔法,ReadOnlyCollection只是有它自己的索引,並實現了IList<T>接口索引不同的實現:

public T Item[int index] { get; } 

T IList<T>.Item[int index] { get; set; } 

如果你投您的列表IList<int>,你會得到一個運行時錯誤而不是編譯錯誤:

((IList<int>)b)[2] = 3; 

編輯:
爲了實現自己的類索引,使用this關鍵字:

public T this[int index] { get { ... } } 

T IList<T>.this[int index] { get { ... } set { ... } } 
+0

這是我的想法,但是當我嘗試在我自己的類中實現IList 時,它不會編譯 – 2009-09-11 09:52:52

+0

什麼是編譯錯誤消息? – thecoop 2009-09-11 10:18:03

+0

@EsbenP:要在類中實現它,語法與文檔中顯示的簽名不同。請參閱上面的修改。 – Guffa 2009-09-11 13:37:28

相關問題