1

次のクラスでは、T を反復処理するために IEnumerable(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>クラスを見てください。typeのプロパティと type のプロパティを実装IEnumerator<KeyValuePair<TKey, TValue>>して公開します。ValuesIEnumerable<TValue>KeysIEnumerable<TKey>

于 2013-08-18T12:45:29.433 に答える
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 に答える