Skip to content

Instantly share code, notes, and snippets.

@yukpiz
Last active October 1, 2016 06:47
Show Gist options
  • Select an option

  • Save yukpiz/87def4a1a77540004183c37bec0b1e80 to your computer and use it in GitHub Desktop.

Select an option

Save yukpiz/87def4a1a77540004183c37bec0b1e80 to your computer and use it in GitHub Desktop.

LINQ with C#

ここではLINQ to Objectについてまとめます。

LINQの基本


List<string>のリスト要素に対して、特定の要素を抽出したり、
全ての要素に処理を施す場合、どのように書くのでしょうか。

LINQの使えない言語を使っていると、以下のようなforeachを普通に書いてしまいます。

List<Stage> stages = new List<Stage>();
//stagesはStageクラスのリストとする

foreach (stage in stages) {
    //抽出条件1
    //抽出条件2
    ...
    
    //抽出結果に対する処理
}

こう書いてしまうと、抽出条件と結果に対する処理が入り混じって、
非常に読みづらいコードになりがちです。

仕様の追加や変更で条件分岐が増えていって・・・
となるともはや画面に収まりきらないforeach文になったりします。

これをLINQを使って書いてみます。

List<Stage> stages = new List<Stage>();
//stagesはStageクラスのリストとする

var filtered = stages
    .Where(stage => {条件式1})
    .Where(stage => {条件式2});

foreach (stage in filtered) {
    //抽出結果に対する処理
}

これだと、抽出条件をまとめて適用した処理と、
抽出結果に対する処理が明確に分かれており、
修正が必要な箇所をすぐに突き止めることができそうです。

このように配列やリストの属性を持ったオブジェクトに対して、
抽出や射影といった処理を施し、結果をまとめることができます。

要素を抽出する


ここではLINQの拡張メソッドである抽出の機能について書きます。
上記で使った抽出機能はWhereでしたが、他にも様々な拡張メソッドが用意されています。
特定の要素を1つに抽出する場合、指定した要素がなければ例外を送出しますが、
OrDefaultが付く場合は型の規定値が返るようになります。

List<Stage> stages = new List<Stage>();
//stagesはStageクラスのリストとする

/*
指定したインデックスにある要素を抽出します。
*/
var filtered = stages.ElementAt(1);
var filtered = stages.ElementAtOrDefault(1);

/*
最初の要素を抽出します。
*/
var filtered = stages.First();
var filtered = stages.FirstOrDefault();

/*
最後の要素を抽出します。
*/
var filtered = stages.Last();
var filtered = stages.LastOrDefault();

/*
リスト要素が単一の場合にそれを返します。
単一でなければ例外、もしくは規定値を返します。
*/
var filtered = stages.Single();
var filtered = stages.SingleOrDefault();

/*
条件式を満たす要素を全て抽出します。
*/
var filtered = stages.Where(stage => stage.id == 1);

/*
重複を除いた要素を全て抽出します。
*/
var filtered = stages.Distinct();

/*
先頭から指定数飛ばした後、残りの要素を全て抽出します。
*/
var filtered = stages.Skip(1);

/*
先頭から条件式を満たす要素を飛ばし、
満たさない要素以降の全ての要素を抽出します。
*/
//stage.idが3以降の要素を全て抽出する。
var filtered = stages.SkipWhere(stage => stage.id != 3);

/*
先頭から指定数分の要素を抽出します。
*/
var filtered = stages.Take(3);

/*
先頭から条件式を満たす要素を抽出します。
条件を満たさない要素が現れた時、それ以降の要素は処理されません。
*/
//stage.idが3でない要素を抽出し、3が現れたら抽出を終える。
var filtered = stages.TakeWhere(stage => stage.id != 3);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment