がその列挙子を として定義しているのに、List<T>
その列挙子を として定義していることに気付きました。違いは何ですか?クラスの列挙子を作成する場合、どちらが望ましいでしょうか?struct
ArrayList
class
編集:を使用して要件を満たすことができないyield
ため、独自の列挙子を実装しています。List<T>
とは言っても、の行に従って構造体として実装した方が良いのではないかと思います。
がその列挙子を として定義しているのに、List<T>
その列挙子を として定義していることに気付きました。違いは何ですか?クラスの列挙子を作成する場合、どちらが望ましいでしょうか?struct
ArrayList
class
編集:を使用して要件を満たすことができないyield
ため、独自の列挙子を実装しています。List<T>
とは言っても、の行に従って構造体として実装した方が良いのではないかと思います。
この他の人と同じように、私はクラスを選択します。可変構造体は厄介です。(そして、Jared が示唆するように、私は反復子ブロックを使用します。列挙子を手作業でコーディングするのは面倒です。)
問題を引き起こす変更可能な構造体であるリスト列挙子の例については、このスレッドを参照してください...
理由リストが構造体列挙子を使用するのは、foreach ステートメントでのガベージ生成を防ぐためです。CF には世代別 GC がなく、CF は通常、パフォーマンスの問題をすぐに引き起こす可能性のある低パフォーマンスのハードウェアで使用されるため、Compact Framework 用にプログラミングしている場合は特に、これはかなりの理由です。
また、いくつかの投稿された例では可変構造体が問題の原因ではないと思いますが、値型がどのように機能するかをよく理解していないプログラマーです。
C# で列挙子を記述する最も簡単な方法は、"yield return" パターンを使用することです。例えば。
public IEnumerator<int> Example() {
yield return 1;
yield return 2;
}
このパターンは、すべての列挙子コードを内部で生成します。これにより、決定はあなたの手から離れます。
を使って書きyield return
ます。
class
またはのどちらかを選択する理由についてはstruct
、 astruct
にすると、インターフェイスとして返されるとすぐにボックス化されるため、struct
追加のコピーが発生するだけです。そのポイントが見えない!
列挙子は、元のコレクションの次の値に移動するために内部状態を更新する必要があるため、本質的に変化する構造です。
私の意見では、構造体は不変であるべきなので、クラスを使用します。
の実装はIEnumerable<T>
クラスを返す必要があります。パフォーマンス上の理由からGetEnumerator
、列挙に必要なメソッドを提供するが実装しない構造体を返すメソッドがあると便利な場合がありますIEnumerator<T>
。IEnumerable<T>.GetEnumerator
このメソッドは、明示的に実装する必要がある とは異なる必要があります。
このアプローチを使用すると、クラスが C# または vb.net で foreach または "For Each" ループを使用して列挙される場合、または列挙を実行するコードが列挙子が構造体であることを認識しているが回避する任意のコンテキストで、パフォーマンスが向上します。列挙子がボックス化されて値で渡されるときに発生する落とし穴。
@Earwicker を拡張するには: 通常、列挙子の型を記述せず、代わりyield return
にコンパイラに記述させることを使用する方がよいでしょう。これは、自分で行うと見逃してしまう可能性のある重要な微妙な点がいくつかあるためです。
使用方法の詳細については、 SO の質問「C# で使用される yield キーワードは何ですか?」を参照してください。
また、 Raymond Chenの一連のブログ投稿 (「C# でのイテレーターの実装とその結果」: パート1、2、3、および4 )では、イテレーターを使用せずにイテレーターを適切に実装する方法を示しています。これは、それがいかに複雑であるかを示しています。 、およびなぜ使用する必要があるのか 。yield return
yield return