简体   繁体   English

在泛型类中实现多个迭代器-C#-IEnumerable(T)

[英]Implementing multiple iterators in generic class - c# - IEnumerable(T)

In the following class, I have implemented succesfully IEnumerable(T) in order to iterate through T. In the same class I was able to implement IEnumerable(DLLItem(T)) to iterate through DLLItem(T). 在下面的类中,我成功实现了IEnumerable(T)以便通过T进行迭代。在同一类中,我能够实现IEnumerable(DLLItem(T))来通过DLLItem(T)进行迭代。 Both are working independantkly. 两者都在独立工作。 It's probably a basic question. 这可能是一个基本问题。 What should I do to have both iterators working together in the same class ? 我应该怎么做才能让两个迭代器在同一个类中一起工作? I've tried several possibilities getting always compiler errors... 我尝试了几种可能总是导致编译器错误的可能性...

With IEnumerable(T) 与IEnumerable(T)

public class DLL<T> :   IEnumerable<T>
{
    ...
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public IEnumerator<T> GetEnumerator()
    {
    ...
        yield return ...
    ...
    }
    ...
}

with IEnumerable(DLLItem(T)) 与IEnumerable(DLLItem(T))

public class DLL<T> :   IEnumerable<DLLItem<T>>
{
    ...
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public IEnumerator<DLLItem<T>> GetEnumerator()
    {
    ...
        yield return ...
    ...
    }
    ...
}

In advance, thanks for your support... 预先感谢您的支持...


Solution as suggested by @dasblinkenlight (see below) @dasblinkenlight建议的解决方案(请参见下文)


public class DLLItemEnum<T> : IEnumerable<DLLItem<T>>
{
    DLL<T> dll;
    public DLLItemEnum(DLL<T> d)
    {
        dll = d;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public IEnumerator<DLLItem<T>> GetEnumerator()
    {
        ...
            yield return ...
        ...
    }
    public static explicit operator DLLItemEnum<T>(DLL<T> d)
    {
        DLLItemEnum<T> i = new DLLItemEnum<T>(d);
        return i;
    }
}
public class ItemEnum<T> : IEnumerable<T>
{
    DLL<T> dll;
    public ItemEnum(DLL<T> d)
    {
        dll = d;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public IEnumerator<T> GetEnumerator()
    {
        ...
            yield return ...
        ...
    }
    public static explicit operator ItemEnum<T>(DLL<T> d)
    {
        ItemEnum<T> i = new ItemEnum<T>(d);
        return i;
    }

public class DLL<T> 
{
     ...
}
class Test
{
    static void Main(string[] args)
    {
        ...
        foreach (int i in (ItemEnum<int>)z)
            Console.WriteLine(i);
        foreach (DLLItem<int> i in (DLLItemEnum<int>)z)
           Console.WriteLine(i.Data);
        ...
    }
}

It's possible, but it will be messy to use. 有可能,但是使用起来很麻烦。

You have to implement both the IEnumerable<DLLItem<T>> and IEnumerable<T> interfaces: 您必须同时实现IEnumerable<DLLItem<T>>IEnumerable<T>接口:

public class DLL<T> :   IEnumerable<DLLItem<T>>, IEnumerable<T>

The GetNumerator methods will collide, so you would have to resort to explicit interface implemenation, which forces the caller to cast the object to the right interface type before accessing the enumerator: GetNumerator方法将发生冲突,因此您必须诉诸显式接口实现,这会强制调用者在访问枚举器之前将对象转换为正确的接口类型:

var dllItems = ((IEnumerable<DLLItem<T>>)someDll);
var Ts = ((IEnumerable<T>)someDll);

My recommendation is to not go that way. 我的建议是不要那样走。 Instead expose properties for one or both of the enumerators. 而是公开一个或两个枚举器的属性。 Look for example at the Dictionary<TKey, TValue> class. 例如查看Dictionary<TKey, TValue>类。 It implements IEnumerator<KeyValuePair<TKey, TValue>> and exposes a Values property of type IEnumerable<TValue> and a Keys property of type IEnumerable<TKey> . 它实现IEnumerator<KeyValuePair<TKey, TValue>>并公开IEnumerable<TValue>类型的Values属性和IEnumerable<TKey>类型的Keys属性。

Since IEnumerable.GetEnumerator() is shared among all generic IEnumerable objects, you cannot implement them both in the same class. 由于IEnumerable.GetEnumerator()在所有通用IEnumerable对象之间共享,因此您不能在同一类中同时实现它们。 You have two options in making it work: 您可以通过两种选择使它起作用:

  • Provide two properties, EnumerableItem and EnumerableDllItem , that produce different iterator objects, the way suggested in this answer , or 提供两个属性EnumerableItemEnumerableDllItem ,它们产生不同的迭代器对象( 此答案中建议的方式),或者
  • Make separate IEnumerable classes - ItemEnumerable<T> and DllItemEnumerable<T> . 制作单独的IEnumerableItemEnumerable<T>DllItemEnumerable<T> Do not implement IEnumerable in DLL<T> at all, and provide two conversion operator from DLL<T> to ItemEnumerable<T> and to DllItemEnumerable<T> . 完全不要在DLL<T>中实现IEnumerable ,而是提供两个从DLL<T>ItemEnumerable<T>DllItemEnumerable<T>转换运算符。 Users would be able to decide on what iterator to use by inserting a cast. 用户将可以通过插入演员表来决定使用哪种迭代器。

In general prefer composition over inheritance. 通常,优先选择组合而不是继承。

The following class is easy to ceate and to use: 以下课程很容易使用和使用:

public class DLL<T> : IEnumerable<T>
{
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerator<T> GetEnumerator()
    {
        throw new NotImplementedException("Need to implement");
    }

    // Compose, not inherit
    public IEnumerable<DLLItem<T>> DLLItems
    {
        get
        {
            throw new NotImplementedException("Need to implement");
        }
    }
}

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

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