简体   繁体   English

接口实现和返回类型

[英]Interface implementations and return types

The List<T> class implements the IEnumerable<T> interface. List<T>类实现IEnumerable<T>接口。 It has a method GetEnumerator that returns a List<T>.Enumerator . 它有一个方法GetEnumerator ,它返回一个List<T>.Enumerator

I have a class as below, which gives a compile error saying the return type of GetEnumerator doesn't match the interface. 我有一个如下所示的类,它给出了一个编译错误,说GetEnumerator的返回类型与接口不匹配。

public class InsertionSortedSet<T> : IEnumerable<T>
{
    public struct Enumerator : IEnumerator<T>
    {
        // Required interface implemented
    }

    // Other interface methods implemented

    public Enumerator GetEnumerator()
    {
        return new Enumerator(this);
    }
}

'Entities.Helpers.InsertionSortedSet' does not implement interface member 'System.Collections.Generic.IEnumerable.GetEnumerator()'. 'Entities.Helpers.InsertionSortedSet'未实现接口成员'System.Collections.Generic.IEnumerable.GetEnumerator()'。 'Entities.Helpers.InsertionSortedSet.GetEnumerator()' cannot implement 'System.Collections.Generic.IEnumerable.GetEnumerator()' because it does not have the matching return type of 'System.Collections.Generic.IEnumerator'. 'Entities.Helpers.InsertionSortedSet.GetEnumerator()'无法实现'System.Collections.Generic.IEnumerable.GetEnumerator()',因为它没有匹配的返回类型'System.Collections.Generic.IEnumerator'。

Given that List<T> seems to return it's own Enumerator class (not the interface) and yet it does implement the Enumeration<T> interface I'm confused, as I can't see what i've got different to that class. 鉴于List<T>似乎返回它自己的Enumerator类(不是接口)但它确实实现了Enumeration<T>接口我很困惑,因为我看不出我对那个类有什么不同。

What's wrong with my setup that makes it fail, where List<T> works? 我的设置有什么问题导致它失败, List<T>在哪里工作?


I want to return a InsertionSortedSet<T>.Enumerator rather than the interface as it avoids boxing, which I need to cut out. 我想返回一个InsertionSortedSet<T>.Enumerator而不是接口,因为它避免了拳击,我需要删除。

It's complaining because GetEnumerator() returns IEnumerator<T> for the IEnumerable<T> interface. 它抱怨,因为GetEnumerator()为IEnumerable<T>接口返回IEnumerator<T> To satisfy, your type must return IEnumerator<T> (and an explicit one for IEnumerator as well). 要满足,您的类型必须返回IEnumerator<T> (以及IEnumerator的显式)。

But, many times it's desirable for a class to return a more specific type than the interface specifies, but interfaces don't allow for covariant return types like that. 但是,很多时候,类需要返回比接口指定的更具体的类型,但是接口不允许这样的协变返回类型。 So to do this, you can do what List<T> does and have GetEnumerator() return your specific enumerator, but you must also implement explicit implementations for IEnumerable.GetEnumerator() that returns an IEnumerator and for IEnumerable<T>.GetEnumerator() that returns an IEnumerator<T> : 所以要做到这一点,你可以做List<T>做的事情并让GetEnumerator()返回你的特定枚举器,但是你还必须实现IEnumerable.GetEnumerator() 显式实现,它返回一个IEnumeratorIEnumerable<T>.GetEnumerator()返回IEnumerator<T>

    // This is your specific version, like List<T> does
    public Enumerator GetEnumerator()
    {
        return new Enumerator(this);
    }

    // This is the one with the return value IEnumerator<T> expects
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return new Enumerator(this);
    }

    // Plus, it also expects this as well to satisfy IEnumerable
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

If you look at List<T> you'll see that it implements GetEnumerator() three times: 如果查看List<T>您会看到它实现了三次GetEnumerator()

  • Once explicitly for IEnumerable<T> 一旦明确用于IEnumerable<T>
  • Once explicitly for Enumerable 一旦明确为Enumerable
  • Once with a very list-specific return 一次具有特定于列表的返回

You could do the same in your class if you wish (which it sould like is the way you began) but if you do that you must explicitly implement IEnumerable<T>.GetEnumerator() and IEnumerable.GetEnumerator() 如果你愿意的话,你可以在你的班级做同样的事情(这就像你开始的那样)但如果你这样做,你必须明确地实现IEnumerable<T>.GetEnumerator()IEnumerable.GetEnumerator()

If you navigate to the definition, you can see the other definitions in the object browser by selecting the different interfaces it satisfies (or by assigning a List<T> instance to an IEnumerable or IEnumerable<T> reference and going to definition): 如果导航到定义,可以通过选择它满足的不同接口(或通过将List<T>实例分配给IEnumerableIEnumerable<T>引用并转到定义)来查看对象浏览器中的其他定义:

对象资源管理器截图

To allow a class to be iterated using foreach no need to implement any interface. 要允许使用foreach迭代类,不需要实现任何接口。 All what you need is implementing GetEnumerator method that returns your Enumerator<T> . 您需要的只是实现返回Enumerator<T> GetEnumerator方法。

But if you want your class to support standard iteration interface IEnumerable<T> you may implement it explicity: IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } 但是如果你希望你的类支持标准的迭代接口IEnumerable<T>你可以实现它明确: IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }

What you are looking for is called return type covariance, more here Does C# support return type covariance? 您正在寻找的是返回类型协方差,更多这里C#是否支持返回类型协方差?

This can be achieved by using explicit implementation of interface to return IEnumerator<T> and implement public method of same name to return Enumerator. 这可以通过使用接口的显式实现来返回IEnumerator<T>并实现同名的公共方法来返回Enumerator来实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM