如何在我的实现IEnumerable <foo>的Dictionary包装器类中实现IEnumerable?</foo>

时间:2011-10-07 20:17:11

标签: c# ienumerable

我正在尝试为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在从元数据生成方法存根时不会列出那些。 (见前一个问题:Why does the VS Metadata view does not display explicit interface implemented members

在发布此问题之前,我曾尝试检查List<T>(通过Visual Studio中的“转到定义”)以查看是否需要实现多个版本的GetEnumerator。我想这不是最可靠的检查方式。

无论如何,我将此标记为已回答。谢谢你的帮助。

7 个答案:

答案 0 :(得分:12)

添加以下显式接口实现:

IEnumerator IEnumerable.GetEnumerator()
{
    return this.GetEnumerator();
}

虽然IEnumerator<T>IEnumerator,但IEnumerable的合同明确返回IEnumerator,而不是IEnumerator<T>

答案 1 :(得分:5)

实施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

}

答案 2 :(得分:4)

问题在于.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();
}

答案 3 :(得分:2)

只要通用IEnumerable{T}继承IEnumerable,您也必须实施IEnumerable.GetEnumerator()。你可以明确地这样做:

IEnumerator IEnumerable.GetEnumerator()
{
       return GetEnumerator();
}

答案 4 :(得分:2)

您已经对主要问题有几个答案。我会回答你编辑中提出的问题......

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() { /* ... */ }

答案 5 :(得分:0)

实现通用IEnumerable接口时,还必须实现非通用IEnumerable接口。错误是关于缺少的非泛型方法。

答案 6 :(得分:0)

这是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();
    }
相关问题