1

在下面的类中,我成功实现了 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);
        ...
    }
}
4

3 回答 3

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>>并公开了ValuestypeIEnumerable<TValue>的属性和 type 的Keys属性IEnumerable<TKey>

于 2013-08-18T12:45:29.433 回答
1

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

  • 提供两个属性,EnumerableItemEnumerableDllItem,产生不同的迭代器对象,这个答案中建议的方式,或者
  • 制作单独的IEnumerable课程 -ItemEnumerable<T>DllItemEnumerable<T>. 根本不实现IEnumerablein DLL<T>,并提供两个转换运算符 from DLL<T>toItemEnumerable<T>和 to DllItemEnumerable<T>。用户将能够通过插入强制转换来决定使用什么迭代器。
于 2013-08-18T12:48:25.077 回答
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");
        }
    }
}
于 2013-08-18T18:53:42.180 回答