web-dev-qa-db-ja.com

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

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

次に、位置1に「2」を配置するように並べ替えます(例:「2」、「1」、「3」)。

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

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

これはうまくいくようですが、時々奇妙な結果が得られます。順序が間違っているか、リストのアイテムが削除されている場合があります!

何か案は? List<T>は順序を保証しますか?

関連する:

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

221

List<> クラスは順序付けを保証します-リストを明示的にソートしない限り、重複を含め、追加した順にリストに物が保持されます。

MSDNによると:

... List「アクセス可能なオブジェクトの強く型付けされたリストを表しますby index。」

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

Remove()Insert()の呼び出しの前に他のすべてのアイテムを1か所下に移動するため、リスト内でアイテムを後で移動している場合、コードから奇妙な結果が得られる可能性があります。

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

288
Bevan

インデックス付きの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);

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

EDIT:あるいは、状況に応じて、カスタム比較子(Sort)を使用してIComparerにすることもできます。

34
Joel Goodwin

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

9
M4N

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

1
Asaf

これは、リスト内のアイテムを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
ChrisF