如何在实现 IEnumerable 的字典包装类中实现 IEnumerable?

发布于 2024-12-09 03:36:57 字数 1827 浏览 0 评论 0 原文

我正在尝试为 Dictionary 创建一个包装器。

Dictionary 实现 IEnumerable>,但我希望我的包装类实现 IEnumerable >。所以我尝试了这个:

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,而 IEnumerator 是一个IEnumerator

编辑:

显式实现 IEnumerator.GetEnumerator() 的解决方案有效。然而,我现在想知道为什么当我在 List 上“转到定义”时,我只看到 GetEnumerator 的一个定义: public List.Enumerator GetEnumerator();

显然,List 可以有一个 GetEnumerator 方法,该方法返回同时实现 < code>IEnumeratorIEnumerator,但我必须为每个都有一个方法?

编辑:

正如下面 LukeH 的回答,List确实包含显式接口实现。显然,当从元数据生成方法存根时,Visual Studio 不会列出这些内容。 (请参阅上一个问题:为什么 VS 元数据视图不显示显式接口实现的成员

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

无论如何,我将其标记为已回答。感谢您的帮助。

I'm trying to create a wrapper for a Dictionary<String,Foo>.

Dictionary<String,Foo> implements IEnumerable<KeyValuePair<String,Foo>>, but I want my wrapper class to implement IEnumerable<Foo>. So I tried this:

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

}

However I get this error:

'FooCollection' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'. 'FooCollection.GetEnumerator()' cannot implement 'System.Collections.IEnumerable.GetEnumerator()' because it does not have the matching return type of 'System.Collections.IEnumerator'.

However I don't understand this error, because FooCollection.GetEnumerator() returns an IEnumerator<Foo>, and IEnumerator<Foo> is an IEnumerator.

EDIT:

The solution of explicitly implementing IEnumerator.GetEnumerator() works. However I'm now wondering why when I "Go to definition" on a List<T> I see only one definition of GetEnumerator:
public List<T>.Enumerator GetEnumerator();

Apparently List<T> can have a single GetEnumerator method that returns something that implements both IEnumerator<T> and IEnumerator, but I have to have one method for each?

EDIT:

As answered by LukeH below, List<T> does include the explicit interface implementations. Apparently Visual Studio just doesn't list those when generating method stubs from the metadata. (See this previous question: Why does the VS Metadata view does not display explicit interface implemented members )

Before posting this question I had tried checking List<T> (via "Go to Definition" in Visual Studio) to see if I needed to implement multiple versions of GetEnumerator. I guess this wasn't the most reliable way to check.

Anyway, I'm marking this as answered. Thanks for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

慕烟庭风 2024-12-16 03:36:57

添加以下显式接口实现:

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

虽然 IEnumerator 是一个 IEnumerator,但 IEnumerable 的协定返回一个 IEnumerator > 具体来说,不是 IEnumerator

Add the following explicit interface implementation:

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

Although IEnumerator<T> is an IEnumerator, the contract for IEnumerable returns an IEnumerator specifically, not an IEnumerator<T>

帅气尐潴 2024-12-16 03:36:57

实现 IEnumerable 时,您还必须显式实现 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

}

When implementing IEnumerable<T>, you must also explicitly implement IEnumerable.GetEnumerator(). The method for the generic interface is not valid in and of itself as an implementation for the non-generic method contract. You can have one call the other, or since you have a child object whose enumerator you are using, just copy/paste;

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

}
冰葑 2024-12-16 03:36:57

问题是 .NET 中不存在返回类型协方差这样的东西 - IEnumerator M()IEnumerator 。 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();
}

The problem is that there is no such thing as return type covariance in .NET - IEnumerator M() and IEnumerator<Foo> M() are completely different methods.

The workaround is that you have to implement the non-generic version explicitly:

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();
}
那一片橙海, 2024-12-16 03:36:57

只要通用 IEnumerable{T} 继承 IEnumerable 您必须实施IEnumerable.GetEnumerator() 也是如此。您可以像这样明确地执行此操作:

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

As long as generic IEnumerable{T} inherit IEnumerable You have to implement IEnumerable.GetEnumerator() as well. You can do it explicitly like:

IEnumerator IEnumerable.GetEnumerator()
{
       return GetEnumerator();
}
对你再特殊 2024-12-16 03:36:57

对于您的主要问题,您已经有了几个答案。我将回答您在编辑中提出的问题...

List 类实际上具有三个 不同的 GetEnumerator 方法: public 方法当编译时实例本身被键入为 List 时调用,并且有两个显式接口实现来满足IEnumerable/IEnumerable 合约。所有三个方法返回的枚举器对象在幕后都是相同的 List.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() { /* ... */ }

You've already had several answers to your main question. I'll answer the question raised in your edit...

The List<T> class actually has three different GetEnumerator methods: The public method that's called when the compile-time instance is typed as List<T> itself, and two explicit interface implementations to meet the IEnumerable/IEnumerable<T> contracts. The enumerator objects returned by all three methods are all the same List<T>.Enumerator type behind-the-scenes.

// Public method
public List<T>.Enumerator GetEnumerator() { /* ... */ }

// IEnumerable<T> explicit interface implementation
IEnumerator<T> IEnumerable<T>.GetEnumerator() { /* ... */ }

// IEnumerable explicit interface implementation
IEnumerator IEnumerable.GetEnumerator() { /* ... */ }
风月客 2024-12-16 03:36:57

当您实现通用 IEnumerable 接口时,您还必须实现非通用 IEnumerable 接口。该错误与缺少非泛型方法有关。

When you implement the generic IEnumerable interface, you also have to implement the non generic IEnumerable interface. The error is about the missing non generic method.

我的影子我的梦 2024-12-16 03:36:57

这是 IEnumerable 的声明:

public interface IEnumerable<out T> : IEnumerable
{
    new IEnumerator<T> GetEnumerator();
}

注意 new 关键字。

下面是 IEnumerable 的声明:

public interface IEnumerable
{

    IEnumerator GetEnumerator();
}

现在您有了一个 GetEnumerator 方法,但是您要实现这两个方法中的哪一个呢?因此,您需要添加非泛型版本的显式实现:

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

Here's the declaration of IEnumerable:

public interface IEnumerable<out T> : IEnumerable
{
    new IEnumerator<T> GetEnumerator();
}

notice the new keyword.

Here's the declaration of IEnumerable:

public interface IEnumerable
{

    IEnumerator GetEnumerator();
}

So now you have a GetEnumerator method, but which one of those two are you implementing? Therefore, you need to add an explicit implementation of the non-generic version:

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文