順序付けされた列挙:IEnumerableまたは配列(C#で)?


8

典型的なコンテキスト:要素が順序付けされていると見なすコレクションの拡張メソッドを作成します。関数はインデックス0から始まり、順序が重要です。例:アイテムのシーケンスまたはインデックスによるグループ化

しかし、私は常に拡張すべきことの困惑:IEnumerable<T>またはT[]。私の理論的根拠は明確な目的でした:配列には順序付けの概念がありますが、IEnumerableは多くの一般的なコレクションによって実装されますが、すべてに順序付けの概念があるわけではありません。

  • 辞書-順不同
  • HashSet-順不同
  • LinkedList-順序付け
  • リスト-注文済み
  • キュー-注文済み
  • SortedDictionary-ソート済み(元の順序ではない)
  • SortedList-ソートされた(元の順序ではない)
  • SortedSet-ソート済み(元の順序ではない)
  • スタック-反転

同様に、注文される場合と注文されない場合がある他の実装。

また、列挙が完了していない場合に列挙子がリセットされるかどうかは定かではありません。それが心配な場合は、列挙がどの時点で開始されるのか誰が知っているのでしょうか。配列の列挙は常に最初から始まります。

したがって、私にとっては、を拡張する方が理にかなっていT[]ます。しかし、私はそれを正しいと思いますか?心配しすぎですか?「順序付けされた」列挙を保証するための適切なアプローチは何ですか?

回答:


13

列挙が完了していない場合に列挙子がリセットされるかどうかはわかりません。それが心配な場合、誰が列挙を開始するのか誰が知っているのでしょうか。配列の列挙は常に最初から始まります。

これらの2つの文は、列挙可能なパターンがどのように機能するかについて深い誤解があると思います。放棄された列挙子後の列挙とは何か関係があると思う理由を説明できますかか?

列挙は、生成装置である列挙子を。列挙子が放棄された場合でも、列挙子に影響はありません。私が本を販売していて、ボブが本を購入して途中でしか読んでいない場合でも、別の本をアリスに販売したときに、ボブが中断したところから読み始めなければならないということではありません。

私は何を拡張するかについて常に困惑しています:IEnumerable<T>またはT[]。私の理論的根拠は明確な目的でした:配列には順序付けの概念がありますが、IEnumerableは多くの一般的なコレクションによって実装されますが、すべてに順序付けの概念があるわけではありません。

あなたの拡張メソッドは、(1)順不同でコレクションにアクセスする必要がありますか?(2)コレクションに書き込みますか?

もしそうIList<T>なら、延長しますそうでなければ、延長しますIEnumerable<T>ます。ます。

(3)配列を必要とするメソッドにコレクションを渡しますか?

次に、配列を拡張します。

あなたの質問は基本的に「私は動物かキリンを拡張するかどうかわからない」です。拡張方法がキリンに固有でない場合は、動物を拡張します。拡張方法が配列に固有でない場合は、すべてのリストを拡張します。リストに固有でない場合は、すべてのシーケンスを拡張します。シーケンスに固有でない場合は、拡張メソッドが不適切なメカニズムである可能性が高くなります。すべてのオブジェクトを拡張しないことをお勧めします。


列挙可能なパターンがどのように機能するかについての知識が非常に恥ずかしいほど欠けています。私がここにこれを尋ねているのはそのためだと思います。
MPelletier 2011

くそー、私は自分のデータ構造クラスを完全に忘れてしまいました。もちろん、後の列挙には影響しません!私は恥ずかしくて自分自身をカバーしています... :(
MPelletier

@MPelletier:あなたの質問はまだ価値があります。安全ですか/たとえば、順序が重要なアルゴリズムを実行することは意味がありDictionaryますか?おそらく違います。スコット・マイヤーズが言ったように:誤用を防ぐ最善の方法は、そのような使用を不可能にすることです。」。このシナリオでそうすることは可能ですか?
Steven Jeuris

1
@EricLippert:あなたが言及した3つのポイント、配列を拡張する必要がある理由です。本当の質問は、私の以前のコメントのように、誤った使用を防ぐ価値があるでしょうか?あなたはそれについて少し拡大できることを願っています...
Steven Jeuris

@StevenJeuris C#が適切に設計され、ISortedCollection <T>インターフェイスが含まれていれば、質問は不要です。これは、コレクションを並べ替える必要がある場合に拡張します。しかし、そうではないため、コンパイル時の誤用を防ぐ唯一の方法は、過度に狭い型(IList <T>)を拡張するか、IEnumerable <T>を拡張して不要なソートを行うことです。
ジムバルター2014

2

2つの異なる概念を1つにまとめたいと思います。データ構造とそのコンテンツの順序は2つの別個のものです。

注文は難しい問題です。たとえば、人のリストを注文するとどうなりますか?注文/分類キーが定義されている場合でも、方向性があり、null(存在する場合)、日付の問題などをどう処理するかを決定する必要があります。

メソッドでデータの順序付けが重要な場合は、呼び出し元がデータを順序付けするのではなく、セットアップの一部としてデータの順序付けをメソッドが担当する必要があります。文字列が検索される前に、渡された文字列から検索メソッド内にディクショナリが構築される一部の文字列一致アルゴリズムでも同様のアプローチが使用されます。これが正確なケースではないことは知っていますが、考えられる最も近い例です。


2
引数としての順序付け方法...うーん、面白い!
MPelletier

その場合でも、順序は暗黙的である可能性があります。それが私が抱えている主要な問題です。LINQの概念はデータベース機能をエミュレートすることであり、1NFに従って、レコードは順序付けされていないことを理解しています。残念ながら、現実の世界が1NFになることはめったにありません。
MPelletier

「現実の世界が1NFになることはめったにありません」という場合もありますが、ここで説明するケースにどのような影響があるのか​​はわかりません。
NoChance

1NF:「行に上から下への順序付けはありません。」それがここで起こっていることだと思います。大量のルーズな「コレクション」で、ログには上から下への順序があります。LINQは、データベースであるかのようにコレクションで機能するように設計されていますが、上から下への順序付けが存在する可能性があるため、今見たところ矛盾があります。
MPelletier 2011

1

IEnumerableは、所有するコレクションを列挙できることを宣言します。コンテンツについて何も意味しません。これは悪いことではありません。コンテナには、個々のインターフェースに加えて、追加の機能と制限を設定できます。

(私はここで配列がどのように優れているかわかりません-IListや他のコンテナーと同様に、インデックス化可能ですが、データの順序を意味するインデックス付けについては何もありません。リストはちょっと変わっています-いくつかの項目は「順序付けられています」 "挿入順序を維持するという点で、他は並べ替えられた場合と同様に"順序付け "されます。これらは2つの異なるものです。SortedSet/ SortedList / SortedDictionary以外は、データを特定の順序で処理すると想定しないでください。あなた自身のコードの中に。)

ただし、IEnumerableは.OrderByを可能にするLINQ拡張を提供するため、列挙可能なものはすべてIOrderedEnumerableの並べ替え順序で返すことができます。ただし、これはLINQ固有のインターフェイスです(デフォルトでは、SortedSet / SortedList / SortedDictionaryによって実装されていないため、その特定のインターフェイスを拡張しても意味がありません...)


2
私が避けたいのは、「順序付けされた場合のみ」機能する一連の関数を作成することです。数か月後、誰かが順序付けられていないコレクションでライブラリを使用し、なぜファンキーな結果が得られるのか疑問に思います。もちろん、誰もが徹底的に読む優れたドキュメントに加えて。
MPelletier 2011

そして、私はIOrderedEnumerableを拡張してもファンになれないと思います。いくつかのリストは、すでに例えば、解析されたログファイルを考える(注文されている順序は、行番号であるが、それにはポイントがありません。ソートそれが順番に読み込まれた場合、それによって。
MPelletier

拡張メソッドにソートされたコレクションが必要であることをユーザーに通知/警告できるデコレーター/インターフェースは今日ありません。特に任意のデータの場合、データが順序付けされているかどうか(比較機能なしで)どうやって知るのですか?
Joe
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.