C#でコレクションを扱っていると、
-
並び順を変更したい
-
ドラッグ&ドロップで要素を入れ替えたい
-
特定の2要素だけを交換したい
といった場面があります。
この記事では、List<T> の要素を入れ替える方法を紹介します。
インデックス指定で入れ替える
List<T> はインデックスアクセスが可能なので、
一時変数を使えば最も素直に要素を入れ替えられます。
var list = new List<int> { 1, 2, 3, 4 };
int temp = list[1];
list[1] = list[3];
list[3] = temp;
Console.Write($"結果: ");
foreach(int x in list)
{
Console.Write($" {x}");
}
Console.WriteLine("");
// 結果: 1 4 3 2
一時変数を使うオーソドックスな方法になりました。
ジェネリックメソッドとして切り出す
同じ処理を何度も書きたくない場合は、
ヘルパーメソッドにしておくと便利です。
static void Swap<T>(List<T> list, int indexA, int indexB)
{
T temp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = temp;
}
// 以下Swap<T>を呼び出すコード
var list = new List<int> { 1, 2, 3, 4 };
Swap<int>(list, 1, 3);
Console.Write($"結果: ");
foreach(int x in list)
{
Console.Write($" {x}");
}
Console.WriteLine("");
// 結果: 1 4 3 2
範囲チェックを入れて安全版にする
indexがlistの範囲内かのチェックは定番で、概ね同じコードになりますので、メソッド内に埋め込むことが出来そうです。
static bool TrySwap<T>(List<T> list, int indexA, int indexB)
{
if (list == null) return false;
if (indexA < 0 || indexA >= list.Count) return false;
if (indexB < 0 || indexB >= list.Count) return false;
if (indexA == indexB) return true;
T temp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = temp;
return true;
}
// 以下Swap<T>を呼び出すコード
var list = new List<int> { 1, 2, 3, 4 };
bool result = TrySwap<int>(list, 0, 5);
Console.WriteLine($"{result}");
// False
LINQ のソート系やSpan<T>は「仮想の並べ替え・参照」
C# には LINQ の OrderBy / ThenByや Span<T> など、
一見すると要素を並べ替えているように見える仕組みがあります。
しかし、これらの多くは 「実体の並び替え」ではなく「仮想の並べ替え」 です。
LINQ のソートは「新しい列を作る」
このコードは、
-
list自体を書き換えている
→ ❌ 書き換えていない -
並び替え結果を「別の列」として返している
→ ⭕ 正しい
LINQ のソート系は 元の List<T> の要素順を変更しません。
あくまで
「並び替えた結果を、そう見える形で列挙する」
という ビュー(View)を作っているだけ です。
Span<T> は「要素の参照」
Span<T> は高速で低レベルな印象がありますが、
これは
-
新しい配列を作る
-
要素の順番を変える
といった処理ではありません。
Span<T> は 同じメモリを別の視点で参照しているだけ で
こちらもビュー(View)を作っているだけといえます。
「並び替えたい」のか「表示を変えたい」のか
| やりたいこと | 適した手段 |
|---|---|
| データそのものの順序を変えたい | List<T> の Swap / Sort |
| 表示順だけ変えたい | LINQ (OrderBy) |
| 高速に部分データを扱いたい | Span<T> |
特に GUI アプリでは、
-
内部データはそのまま
-
表示だけ並び替える
という設計もよくあります。
最後に
要素の入れ替えは昔からある定番コードフローで、LINQが出てきてお役御免となったかと思もいましたが、そうでも無くいまだ現役なかんじです。

コメント