List <T>は挿入順序を保証しますか?


238

リストに3つの文字列があるとします(例: "1"、 "2"、 "3")。

次に、それらを並べ替えて、位置2に「2」を配置します(たとえば、「2」、「1」、「3」)。

私はこのコードを使用しています(indexToMoveToを1に設定):

listInstance.Remove(itemToMove);
listInstance.Insert(indexToMoveTo, itemToMove);

これは機能するようですが、時々奇妙な結果が出ます。時々、注文が間違っているか、リストのアイテムが削除されています!

何か案は?いList<T>保証順序は?

関連:

List <T>は、アイテムが追加された順に返されることを保証しますか?


3
ここに述べたようにこれは真実ではありません。stackoverflow.com/a/1790318/696517
jrmgx

回答:


311

List<>クラスは、保証の順序付けを行います-ない限り、明示的にソートリストのものは、重複を含む、あなたがそれらを追加するために、リスト内に保持されます。

MSDNによると:

...リスト " インデックスでアクセスできるオブジェクトの強く型付けされたリストを表します。"

これを正確にするには、インデックス値の信頼性を維持する必要があります。したがって、順序は保証されます。

Remove()の呼び出しの前に他のすべての項目を1つ下に移動するため、項目をリストの後半に移動すると、コードから奇妙な結果が得られる場合がありますInsert()

投稿するのに十分な小さいものにコードを要約できますか?


63
今後のグーグルの場合は、ここで、MSDN(太字)からのList(T) の正確な引用を示します。AddList <T>の最後追加するオブジェクト。参照型の場合、値はnullにすることができます。
aolszowka

4
これについてマイクロソフトまたはC#仕様から取得できる、より明確な引用/参照はありますか?@aolszowkaの引用は、挿入順序が保持されていることを明確に示唆しているようですが、技術的には、リストはアイテムが追加された後いつでもコレクションを並べ替えることができ、そのステートメントは引き続き有効です。私はそれについて一生懸命に言いたくありませんが、マネージャーまたはQAが本当に私にこの立場を擁護させたとしたら、その引用だけではあまり自信がありません。
tehDorf 2015

4
確認を得るには、2つの便利な方法が考えられます。まず、ソース読んで満足してください。次に、List優れたコンピュータサイエンス教科書で抽象データ型の定義を確認してください。同じようにQueueしてStackList明確に定義され、予測可能かつ十分に理解するデータ構造である- .NET実装が異なっていた(またはそれが変化した場合)場合、多くのソフトウェアが壊れます。
Bevan

@tehDorf私の見解(それについての議論があった場合)は、次のとおりです。 SortedList、それ以外の場合、明確に明記されていない限り、特定の実装が特定の動作をすることに依存するべきではありません。
aolszowka

1
@achuthakrishnan彼らは別の問題です。リストは、アイテムがリストに追加された順序で保持されることを保証します。LINQ Where()メソッドを使用してリストをフィルター処理する場合、実装は順序内の項目を順番に検討することに依存しています。たまたまそうなのですが(referencesource.microsoft.com/System.Core/System/Linq/…を参照)、これはMSDNに記載されていません。emp.LastOrDefault(x => x.empDept = 'abc')のドキュメンテーションLastOrDefault()がアイテムの順序を維持することを示しているように、私は使用することをお勧めします。
Bevan 2016

36

ここに4つのアイテムとそのインデックスがあります

0  1  2  3
K  C  A  E

KをAとEの間に移動したい場合-位置3と思われるかもしれません。ここでは、削除後にすべてのインデックスが更新されるため、インデックス作成に注意してください。

したがって、最初にアイテム0を削除し、

0  1  2
C  A  E

次に3に挿入します

0  1  2  3
C  A  E  K

正しい結果を得るには、インデックス2を使用する必要がありました。一貫性を持たせるには、(indexToMoveTo-1)に送信する必要がありますif indexToMoveTo > indexToMove。たとえば、

bool moveUp = (listInstance.IndexOf(itemToMoveTo) > indexToMove);
listInstance.Remove(itemToMove);
listInstance.Insert(indexToMoveTo, moveUp ? (itemToMoveTo - 1) : itemToMoveTo);

これは問題に関連している可能性があります。私のコードはテストされていないことに注意してください!

編集:または、状況に該当する場合Sortは、カスタムコンパレーター(IComparer)を使用できます。


Bevanの応答を十分に注意深く読んでいませんでした。私は彼が持っている地面をカバーしました。
ジョエル・グッドウィン、

9
ええ、しかし、あなたはBevanの答えの例といくつかのソリューションコードを詳しく説明して与えたので、あなたの答えは自家のものではなく、私はあなたに投票しました。
Jason S

9

Bevanが言ったように、ただし、リストインデックスは0から始まることに注意してください。要素をリストの先頭に移動する場合は、インデックスを0に挿入する必要があります(例に示すように1ではありません)。


1

これは、アイテムをリストの1つ下に移動するためのコードです。

if (this.folderImages.SelectedIndex > -1 && this.folderImages.SelectedIndex < this.folderImages.Items.Count - 1)
{
    string imageName = this.folderImages.SelectedItem as string;
    int index = this.folderImages.SelectedIndex;

    this.folderImages.Items.RemoveAt(index);
    this.folderImages.Items.Insert(index + 1, imageName);
    this.folderImages.SelectedIndex = index + 1;
 }

これを1つ上に移動するには、次のようにします。

if (this.folderImages.SelectedIndex > 0)
{
    string imageName = this.folderImages.SelectedItem as string;
    int index = this.folderImages.SelectedIndex;

    this.folderImages.Items.RemoveAt(index);
    this.folderImages.Items.Insert(index - 1, imageName);
    this.folderImages.SelectedIndex = index - 1;
}

folderImagesListBoxもちろんなので、リストはListBox.ObjectCollectionでなくですがList<T>、継承元であるIListため、同じように動作します。これは役に立ちますか?

もちろん、前者は選択したアイテムがリストの最後のアイテムでない場合にのみ機能し、後者は選択したアイテムが最初のアイテムでない場合にのみ機能します。


1

操作の順序を変更すると、奇妙な動作を回避できます。最初にリストの適切な場所に値を挿入し、次に最初の位置から値を削除します。参照して削除すると、両方とも削除される可能性があるため、必ずインデックスで削除してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.