C# 基礎からマスターまで — 第6回
コレクションとLINQでデータを扱う
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
ゲームとアプリは多くのデータを保存、検索、並べ替えます。 コレクションを目的に合わせて均等にLINQで処理意図を表現すると、コードが短くなるよりも流れが鮮明になる。
コレクションを選択
var party = new List<Player>();
var itemById = new Dictionary<int, Item>();
var unlockedIds = new HashSet<int>();
itemById.Add(10, new Item(10, "Potion"));
unlockedIds.Add(10);
Listは順序付きリスト、Dictionaryはキー検索、HashSetは値の存在と重複防止に適しています。 Dictionaryにないキーをインデクサーに読み込むと例外が発生するため、TryGetValueを使用できます。
LINQで問い合わせる
List<Monster> targets = monsters
.Where(monster => monster.IsAlive)
.OrderBy(monster => monster.Health)
.Take(3)
.ToList();
生きているモンスターの中で体力の低い三匹を選ぶという意図が演算の順番に現れる。 LINQは元のコレクションを自動的に変更せずに新しい結果フローを作成します。
遅延実行
IEnumerable<Monster> alive = monsters.Where(monster => monster.IsAlive);
monsters.Add(new Monster());
foreach (Monster monster in alive)
{
Console.WriteLine(monster.Health);
}
Whereが返したクエリは通常巡回する時点で実行されます。 途中でオリジナルが変わると結果も変わることがあり、現在の結果を固定するにはToList()で直ちに計算します。
繰り返しコストを確認する
LINQ呼び出しが無条件に遅いわけではありませんが、イテレータ、デリゲート、結果のコレクションを作成できます。 フレームごとに何千回も実行されるパスであれば、単純な繰り返しステートメントとバッファの再利用がより適している可能性があります。
targets.Clear();
foreach (Monster monster in monsters)
{
if (monster.IsAlive)
{
targets.Add(monster);
}
}
まず、読みやすいクエリを作成し、実際の測定で問題が確認された区間だけを変更するのが良い。 コレクションとLINQの鍵は、最も短い文法ではなく、データの保存目的と処理時点を明確にすることです。