Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Final LINQ Extensions II

Final LINQ Extensions II

C# LINQの基礎について解説しています。発表自体はかなり前ですが、現在(.NET 5)においても全く問題ありません。

------

Center CLR Part.3 (DoorKeeperは退会したため、募集エントリは残っていません)

Kouji Matsui

May 10, 2015
Tweet

More Decks by Kouji Matsui

Other Decks in Programming

Transcript

  1. 自己紹介  けきょ (@kekyo2 Kouji Matsui)  LINQ, Async, .NETとか

     Center CLRオーガナイザーです  会社やってます  アーキとかフレームワーク設計とか
  2. アジェンダ  雑魚の始末  クエリ構文との連携  演算子の適用回数を減らすこと  短縮演算子 

    Where条件の合成  LINQ⇔制御構文  強力な武器を手に入れる  更なる演算子  LINQソース  式木の使われ方  IEnumerableへのフォールバック  並列化  Pick it up for Multiple!  TPLとの関係
  3. クエリ構文との連携  クエリ構文は「構文糖」です。  ある「条件」を満たせば、独自の実装をLINQクエリ構文で記述させることが 出来るようになります。  クエリの連結を成立させるには: 条件 内容

    メソッドの種類 インスタンスメソッドでも拡張メソッドでも良い。 演算子の対応 クエリ構文でサポートされている演算子に対応したメソッド名で定義する。 Where, Select, SelectMany, OrderBy(Descending), ThenBy(Descending), Join, GroupBy, Grouping (但し、全部定義する必要はない) メソッド戻り値 前段の演算子の戻り値から、演算子メソッドのオーバーロードを特定可能にする。 列挙可能性 IEnumerable<T>の実装は必須ではない。
  4. クエリ構文との連携  クエリの連結を成立させるには:  System.Linq.Enumerableクラスには、上記の条件を満たした標準演算子 メソッドが定義されている ので、クエリ構文が普通に使える! Enumerable.Where() Enumerable.OrderBy() Enumerable.Select()

    条件 内容 メソッドの種類 インスタンスメソッドでも拡張メソッドでも良い。 演算子の対応 クエリ構文でサポートされている演算子に対応したメソッド名で定義する。 Where, Select, SelectMany, OrderBy(Descending), ThenBy(Descending), Join, GroupBy, Grouping (但し、全部定義する必要はない) メソッド戻り値 前段の演算子の戻り値から、演算子メソッドのオーバーロードを特定可能にする。 列挙可能性 IEnumerable<T>の実装は必須ではない。
  5. 短縮演算子  短縮演算子の種類 機能グループ 演算子 フィルター First / FirstOrDefault Last

    / LastOrDefault 単項(即値) Any / All Max / Min Count パフォーマンスのための演算子だけど、 後から機械的なリファクタリングで対応可能ネ!
  6. LINQ⇔制御構文  あーれれ?目の上のコブだったList<T>が無くなってしまいました。  この例では、アルゴリズムの再考を行うことなく、リファクタリン グ技術のみで、制御構造で書かれた処理をLINQに置き換え、更にメ モリ使用量を劇的に改善しました。  これを実現するポイント: 

    処理中に存在する部品は、「式」化する。入力と出力を明確に分離し、 「入出力」として使用しないように注意する(副作用を持ち込まない)。  より抽象度の高い型を使用する。 配列やList<T>は、IList<T>へ。 IList<T>は、IReadOnlyList<T>へ。 IReadOnlyList<T>は、IEnumerable<T>へ。 非ジェネリックIEnumerableは LINQで使えないので、ここまで。
  7. LINQ⇔制御構文  LINQ→制御構文  逆に、既存のLINQクエリを制御構文に置き換えるのは簡単です。  LINQクエリは「式」であり、まず副作用が無い事が見込める(副作用があ るとまともに動作しない)ため、単純に展開すれば良いのです(whereなら if文に置き換えるなどの、機械的な置換操作)。 

    これが必要になるのは、LINQクエリのパフォーマンスが問題になる場合で す。しかし、難易度が低いので、とりあえずLINQで実装して、後で測定し てから修正でも、全く問題ないと言えます。最終的には、プロダクトリ リースを早める武器の一つとなるでしょう。 だから、データ抽出処理は、 LINQで書かなければならない、のです!
  8. アジェンダ  雑魚の始末  クエリ構文との連携  演算子の適用回数を減らすこと  短縮演算子 

    Where条件の合成  LINQ⇔制御構文  強力な武器を手に入れる  更なる演算子  LINQソース  式木の使われ方  IEnumerableへのフォールバック  並列化  Pick it up for Multiple!  TPLとの関係
  9. 更なる演算子  標準演算子をほぼ網羅  前回と合わせて目指せマスター! 機能グループ 演算子 単項(即値) Average Contains

    SequenceEqual 抽出 DefaultIfEmpty First / FirstOrDefault Last / LastOrDefault Single / SingleOrDefault ElementAt / ElementAtOrDefault Cast / OfType 集合演算 Except / Intersect / Union 単純結合 Concat / Zip 結合 Join / Grouping ジェネレータ Empty / Range / Repeat 演算器 Aggregate
  10. 抽出  DefaultIfEmpty  シーケンスが空の場合は、デフォルト値を返す 152 124 238 54 152

    124 238 54 空ではないので、 そのまま 0 空なので、デフォルト値 default(int) 単一のシーケンスを 返す
  11. 抽出  First / Last  シーケンスの先頭・終端の値を得る 152 124 238

    54 152 54 First シーケンスが空だと どうなる? Last
  12. 抽出  Single / SingleOrDefault  シーケンスの、ただ一つの要素を返す 152 Single 152

    0 SingleOrDefault シーケンスが0個or1個「ではない」 場合は例外がスローされる
  13. 抽出  Single / SingleOrDefaultと書いてあれば、「このシーケンスには複数 の要素が来ることはない」というのが見ただけで分かります。  複数の要素が来たら、バグですよね多分。  コードの「意図」を明確にすることが重要です。

     制御構文からLINQクエリへ: 基本要素(forとかwhileとかifと かswitch)の羅列では、読解に労力を要します。LINQクエリで 記述することで、より高度でありながら抽象度の高い記述が 可能になり、コードの誤りを避けたり摘出が容易になります。  LINQクエリに意図を盛り込む:「どうするか」ではなく、 「何をしたいか」を記述することで、コードがより意図的に なります。コードから意図が読み取りやすいほど、保守性は 劇的に良くなります。  Wikipedia: 「インテンショナルプログラミング」
  14. 抽出  Element / ElementAtOrDefault  指定された位置の要素を返す 152 124 238

    54 238 0 (2) (4) シーケンスが範囲外の場合は、 default(int) が返される
  15. 152 抽出  Cast / OfType  シーケンスの要素をキャストしながら抽出する Cast “ABC”

    124 987.654 152 “ABC” 124 987.654 152 OfType “ABC” 124 987.654 152 124 238 … … … 54 OfTypeは指定された型にキャスト 出来るものだけが抽出される 要素のインスタンスに変化はないが、 IEnumerable<T>のジェネリック引数型が与えられる
  16. 集合演算 123 datas0 datas1 456 1234 3456 121 223 2345

    789 494  Intersect(積集合)
  17. 集合演算 123 datas0 datas1 456 1234 3456 121 223 2345

    789 494 重複する要素は1回しか 列挙されないことに注意  Union(和集合)
  18. 単純結合  Zip(縫い合わせる) 片方で要素数が不足する場合は、 その要素は列挙されない 123 456 789 1234 “ABC”

    “DEF” “GHI” “JKL” 2345 3456 2つの要素を射影させる λ “123:ABC” “456:DEF” “789:GHI” “1234:JKL”
  19. 結合  GroupBy(キーによるグループ化) ID タイトル 123 IT業界の闇について 456 萌に関する101通りの方法 456

    萌に関する101通りの方法 アドバンスド 666 ウォーターフォールがうまくいく3つのポイント 666 ウォーターフォールがうまくいく666つのポイント 789 デスマーチとは 789 デスマーチ再び ID タイトル 123 IT業界の闇について 456 萌に関する101通りの方法 萌に関する101通りの方法 アドバンスド 666 ウォーターフォールがうまくいく3つのポイント ウォーターフォールがうまくいく666つのポイント 789 デスマーチとは デスマーチ再び これこそが、LINQがSQL の延長上「ではない」 最大の強力な武器 同じIDを持つデータを集約したい。 (たまたま同じIDが並んでいるが、 当然IDが離れていても集約する)
  20. 結合  IGrouping<TKey, TElement>インターフェイスは、 IDictionary<TKey, TElement>に似ています。  IDictionaryは、「キー・値」の組のコレクションです。  IGroupingは、値コレクションにキーが付けられた、一つ分のグループです。

    ID タイトル 123 IT業界の闇について 456 萌に関する101通りの方法 456 萌に関する101通りの方法 アドバンスド 666 ウォーターフォールがうまくいく3つのポイント 666 ウォーターフォールがうまくいく666つのポイント 789 デスマーチとは 789 デスマーチ再び ID タイトル 123 IT業界の闇について 456 萌に関する101通りの方法 萌に関する101通りの方法 アドバンスド 666 ウォーターフォールがうまくいく3つのポイント ウォーターフォールがうまくいく666つのポイント 789 デスマーチとは デスマーチ再び 辞書的(IDictionary) グループ化(IEnumerable<IGrouping>)
  21. 結合  グループ化は、従来のデータベースでは実現不可能だった、「階層化された データ」をそのまま処理できます。  データベースで階層化データを扱えないのは、あくまで「表」という構造に縛 られているためです。.NET CLRの世界ではそのような制約はありません。  処理自体は、SQLでのGROUP

    BYに相当しますが、マルチレコードセットのよう な扱いにくい概念ではなく、ごく自然にクラス型にマッピング出来ます。 ID タイトル 123 IT業界の闇について 456 萌に関する101通りの方法 萌に関する101通りの方法 アドバンスド 666 ウォーターフォールがうまくいく3つのポイント ウォーターフォールがうまくいく666つのポイント 789 デスマーチとは デスマーチ再び グループ化されたキー グループ化された値群
  22. ジェネレーター [Ref] [Ref] [Ref] … [Ref] 10000個の参照  Repeatを参照型で使う場合の注意点: FooModel

    単一のインスタンス FooModel FooModel FooModel … FooModel 10000個のFooModel(への参照)
  23. アジェンダ  雑魚の始末  クエリ構文との連携  演算子の適用回数を減らすこと  短縮演算子 

    Where条件の合成  LINQ⇔制御構文  強力な武器を手に入れる  更なる演算子  LINQソース  式木の使われ方  IEnumerableへのフォールバック  並列化  Pick it up for Multiple!  TPLとの関係 その昔、クリスタルの魔力をわが手中に せんとする陰謀が、 「これが最後」というタイトルと共に、 幾度となく繰り返された伝説があった…
  24. 次回予告 Final LINQ Extensions Ⅲ (仮題)  LINQソース  式木の使われ方

     IEnumerableへのフォールバック  並列化  Pick it up for Multiple!  TPLとの関係 近日公開!!!