![](/img/trans.png)
[英]How to Implement GetEnumerator method for class that implements IEnumerable<IEnumerable<T>>
[英]How do I implement IEnumerable in my Dictionary wrapper class that implements IEnumerable<Foo>?
我正在嘗試為Dictionary<String,Foo>
創建一個包裝器。
Dictionary<String,Foo>
實現IEnumerable<KeyValuePair<String,Foo>>
,但我希望我的包裝類實現IEnumerable<Foo>
。 所以我嘗試了這個:
public class FooCollection : IEnumerable<Foo>
{
private Dictionary<string, Foo> fooDictionary = new Dictionary<string, Foo>();
public IEnumerator<Foo> GetEnumerator()
{
return fooDictionary.Values.GetEnumerator();
}
// Other wrapper methods omitted
}
但是我收到此錯誤:
'FooCollection'沒有實現接口成員'System.Collections.IEnumerable.GetEnumerator()'。 'FooCollection.GetEnumerator()'無法實現'System.Collections.IEnumerable.GetEnumerator()',因為它沒有匹配的返回類型'System.Collections.IEnumerator'。
但是我不明白這個錯誤,因為FooCollection.GetEnumerator()
返回一個IEnumerator<Foo>
,而IEnumerator<Foo>
是一個IEnumerator
。
編輯:
顯式實現IEnumerator.GetEnumerator()
的解決方案有效。 但是我現在想知道為什么當我在List<T>
上“去定義”時,我只看到GetEnumerator的一個定義: public List<T>.Enumerator GetEnumerator();
顯然List<T>
可以有一個GetEnumerator
方法,它返回實現IEnumerator<T>
和IEnumerator
,但是我必須有一個方法?
編輯:
正如下面的LukeH所回答的, List<T>
確實包含了顯式接口實現。 顯然,Visual Studio在從元數據生成方法存根時不會列出那些。 (請參閱前一個問題: 為什么VS Metadata視圖不顯示顯式接口實現的成員 )
在發布此問題之前,我曾嘗試檢查List<T>
(通過Visual Studio中的“轉到定義”)以查看是否需要實現多個版本的GetEnumerator。 我想這不是最可靠的檢查方式。
無論如何,我將此標記為已回答。 謝謝你的幫助。
添加以下顯式接口實現:
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
雖然IEnumerator<T>
是一個IEnumerator
,對於合同IEnumerable
返回IEnumerator
具體而言,不是一種IEnumerator<T>
實現IEnumerable<T>
,還必須顯式實現IEnumerable.GetEnumerator()
。 泛型接口的方法本身作為非泛型方法契約的實現無效。 你可以有一個調用另一個,或者因為你有一個你正在使用的枚舉器的子對象,只需復制/粘貼;
using System.Collections;
using System.Collections.Generic;
public class FooCollection : IEnumerable<Foo>
{
private Dictionary<string, Foo> fooDictionary = new Dictionary<string, Foo>();
public IEnumerator<Foo> GetEnumerator()
{
return fooDictionary.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
//forces use of the non-generic implementation on the Values collection
return ((IEnumerable)fooDictionary.Values).GetEnumerator();
}
// Other wrapper methods omitted
}
問題是.NET中沒有返回類型協方差這樣的東西 - IEnumerator M()
和IEnumerator<Foo> M()
是完全不同的方法。
解決方法是您必須顯式實現非泛型版本:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
// this calls the IEnumerator<Foo> GetEnumerator method
// as explicit method implementations aren't used for method resolution in C#
// polymorphism (IEnumerator<T> implements IEnumerator)
// ensures this is type-safe
return GetEnumerator();
}
只要通用IEnumerable {T}繼承IEnumerable你就必須實現IEnumerable.GetEnumerator()
。 您可以明確地執行以下操作:
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
你已經有了幾個主要問題的答案。 我會回答你編輯中提出的問題......
List<T>
類實際上有三種不同的GetEnumerator
方法:當編譯時實例被輸入為List<T>
本身時調用的公共方法,以及兩個用於滿足IEnumerable
/ IEnumerable<T>
契約的顯式接口實現。 所有三種方法返回的枚舉器對象都是幕后的List<T>.Enumerator
類型。
// Public method
public List<T>.Enumerator GetEnumerator() { /* ... */ }
// IEnumerable<T> explicit interface implementation
IEnumerator<T> IEnumerable<T>.GetEnumerator() { /* ... */ }
// IEnumerable explicit interface implementation
IEnumerator IEnumerable.GetEnumerator() { /* ... */ }
實現通用IEnumerable接口時,還必須實現非通用IEnumerable接口。 錯誤是關於缺少的非泛型方法。
這是IEnumerable的聲明:
public interface IEnumerable<out T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
注意新的關鍵字。
這是IEnumerable的聲明:
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
所以現在你有一個GetEnumerator方法,但是你實現了哪兩個呢? 因此,您需要添加非泛型版本的顯式實現:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.