簡體   English   中英

如何在我的實現IEnumerable的Dictionary包裝器類中實現IEnumerable <Foo> ?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM