3

アイテム配列をラップするクラスを実装しています。LINQの使用を容易にするために、クラスにIEnumerable<T>インターフェイスを実装する必要があります。

クラスを実装する最初の「素朴な」試みは次のとおりです。

public class Foo<T> : IEnumerable<T>
{
  private readonly T[] _items;

  public Foo(T[] items) { _items = items; }

  public IEnumerator<T> GetEnumerator() { return _items.GetEnumerator(); } // ERROR

  IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

ただし、配列はIEnumerableインターフェイスのみを実装し、 を実装しないため、これはコンパイルされませんIEnumerable<T>。コンパイルエラーは次のとおりです。

タイプ 'System.Collections.IEnumerator' を 'System.Collections.Generic.IEnumerator<T>' に暗黙的に変換することはできません。明示的な変換が存在します (キャストがありませんか?)

この問題を克服するために、配列を継承するインターフェイスにローカルでキャストします。IEnumerable<T>たとえば、次のようになりますIList<T>

  public IEnumerator<T> GetEnumerator() { 
    return ((IList<T>)_items).GetEnumerator();
  }

これは正常にコンパイルされ、最初のテストでも、クラスが列挙可能なコレクションとして正しく機能することが示されました。

ただし、キャスティングのアプローチは完全に満足できるものではありません。このアプローチに関する注意事項はありますか? より信頼性の高い (タイプセーフな) 方法で問題を解決できますか?

4

3 に答える 3

1

する方が良いようです:

return ((IEnumerable<T>)_items).GetEnumerator();

配列が実装するようIEnumerable<T>に:

[...] このタイプの実装IEnumerableIEnumerable<T>

IEnumerable.GetEnumeratorとの間のあいまいさのため、最初のアプローチは機能しませんでしたIEnumerable<T>.GetEnumerator

IDE 内で表示できない問題については、次の説明を参照してください

.NET Framework 2.0 以降、Array クラスは、、、およびジェネリック インターフェイスを実装System.Collections.Generic.IList<T>System.Collections.Generic.ICollection<T>ますSystem.Collections.Generic.IEnumerable<T>。実装は実行時に配列に提供されるため、ドキュメント ビルド ツールには表示されません。その結果、ジェネリック インターフェイスは Array クラスの宣言構文に表示されず、配列をジェネリック インターフェイス型にキャストすることによってのみアクセスできるインターフェイス メンバー (明示的なインターフェイスの実装) に関するリファレンス トピックはありません。これらのインターフェイスのいずれかに配列をキャストするときに注意すべき重要な点は、要素を追加、挿入、または削除するメンバーが をスローすることNotSupportedExceptionです。

于 2013-10-30T17:25:32.473 に答える