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

时间:2013-08-18 12:37:25

标签: c# generics

在下面的类中,我已经成功实现了IEnumerable(T)以便遍历T.在同一个类中,我能够实现IEnumerable(DLLItem(T))来遍历DLLItem(T)。两者都是独立工作的。这可能是一个基本问题。我应该怎么做才能让两个迭代器在同一个类中一起工作? 我已经尝试了多种可能性来获得编译器错误......

使用IEnumerable(T)

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

使用IEnumerable(DLLItem(T))

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

提前感谢您的支持......


@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);
        ...
    }
}

3 个答案:

答案 0 :(得分:5)

这是可能的,但使用它会很麻烦。

您必须实现IEnumerable<DLLItem<T>>IEnumerable<T>接口:

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

GetNumerator方法将发生冲突,因此您必须求助于显式接口实现,这会强制调用者在访问枚举器之前将对象强制转换为正确的接口类型:

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

我的建议是不要这样做。而是公开一个或两个枚举器的属性。请查看Dictionary<TKey, TValue>课程的示例。它实现IEnumerator<KeyValuePair<TKey, TValue>>并公开类型为Values的{​​{1}}属性和IEnumerable<TValue>类型的Keys属性。

答案 1 :(得分:1)

由于IEnumerable.GetEnumerator()在所有通用IEnumerable对象之间共享,因此您无法在同一个类中实现它们。你有两种选择:

  • 提供两个属性EnumerableItemEnumerableDllItem,它们生成不同的迭代器对象,方法在this answer中建议,或
  • 制作单独的IEnumerable课程 - ItemEnumerable<T>DllItemEnumerable<T>。不要在IEnumerable中实施DLL<T>,并提供从DLL<T>ItemEnumerable<T>DllItemEnumerable<T>的两个转换运算符。用户可以通过插入强制转换来决定使用什么迭代器。

答案 2 :(得分:0)

通常更喜欢构图而不是继承。

以下课程易于终止和使用:

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");
        }
    }
}