超LINQ入門

6,792 views

Published on

LINQ勉強会のハンズオン資料です。
http://atnd.org/events/39864

0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,792
On SlideShare
0
From Embeds
0
Number of Embeds
4,488
Actions
Shares
0
Downloads
0
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

超LINQ入門

  1. 1. road to Linqulien
  2. 2.  米田 大介(三十路後半) ◦ 業務系のSEっポイことしてます。 ◦ C#が好きです。  でも、今業務ではVB.NETを書いてます。 ◦ LINQが好き  なので、VBでもLINQがかけるようになりました。  Room Metroとかに、よくお世話になってます。
  3. 3.  とりあえず ググる 福岡のアイド ル? コッチ
  4. 4. 1. とりあえずコード書いてみましょう 2. リファクタリングしてみます。 3. なんと!? LINQがそこに。 最初はLINQなしでね パチパチパチ
  5. 5.  Project Eulerに挑戦 ◦ 問題1  10未満の自然数のうち, 3 もしくは 5 の倍数になっている ものは 3, 5, 6, 9 の4つがあり,これらの合計は 23 になる. 同じようにして, 1000 未満の 3 か 5 の倍数になっている 数字の合計を求めよ. ◦ 問題2  フィボナッチ数列の項は前の2つの項の和である. 最初の2項 を 1, 2 とすれば, 最初の10項は以下の通りである. 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 数列の項の値が400万より小さい, 偶数値の項の総和を求め よ.  「Project Euler 日本語」で検索!!
  6. 6. public static int Problem1(int limit) { int sum = 0; for (int i = 1; i < limit; i++) { if (i % 3 == 0 || i % 5 == 0) { sum += i; } } return sum; }
  7. 7. Public Function Problem1(ByVal limit As Integer) Dim sum = 0 For i = 1 To limit - 1 If i Mod 3 = 0 OrElse i Mod 5 = 0 Then sum += i End If Next Return sum End Function
  8. 8. public static int Problem2(int limit) { int sum = 0; int a = 1; int b = 1; while (b < limit) { if (b % 2 == 0) { sum += b; } var temp = a; a = b; b = a + temp; } return sum; }
  9. 9. Public Function Problem2(ByVal limit As Integer) Dim sum = 0 Dim a = 1 Dim b = 1 While b < limit If b Mod 2 = 0 Then sum += b End If Dim temp = a a = b b = a + temp End While Return sum End Function
  10. 10. public static int Problem1(int limit) { int sum = 0; for (int i = 1; i < limit; i++) { if (i % 3 == 0 || i % 5 == 0) { sum += i; } } return sum; } 数列生成 終了条件 抽出条件 合計処理
  11. 11. public static int Problem2(int limit) { int sum = 0; int a = 1; int b = 1; while (b < limit) { if (b % 2 == 0) { sum += b; } var temp = a; a = b; b = a + temp; } return sum; } 数列生成 終了条件 抽出条件 合計処理
  12. 12.  現状の問題 ◦ 処理が分散して、入り交じっている。  これを ◦ 同じ処理はまとめる ◦ 違う処理は分ける  なぜ? ◦ 再利用する ◦ 組み合わせ爆発を防ぐ ◦ わかりやすい
  13. 13.  同じコードは何度も書きたくない ◦ DRY ◦ 結果としてコードが短くなる 共通部分は、 メソッドにしたい 小難しい部分は、 ライブラリを呼ぶだけが いい
  14. 14.  複雑さは乗数で増えていく。 ◦ 何時、何処で、誰が、何をした。 自然数 フボナッチ 数 1000未満 400万未満 偶数 3か5で 割切れる 合計 平均 素数 先頭の100 個 標準偏差奇数番目 ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・ ・
  15. 15.  分けたからわかりやすい ◦ 自然言語として、わかりやすい単位で分ける ◦ 適当な範囲で名前を付けられる
  16. 16.  数列生成部分を分けてみる ◦ 戻り値の型は?  List or Array  あらかじめ必要となる要素数が分かってないと、生成できない。 ◦ じゃ、どうする?  IEnumerable<T>
  17. 17.  列挙可能型 ◦ 唯一のメソッドはGetEnumerator()  MoveNextとCurrentを定義するIEnumerator<T>を返す ◦ List<T> / T[] 等、全てのコレクションの基底Inte rface ◦ foreachで回せる ◦ 実際に値が必要になるときまで評価を遅延する実装が可 能  可能とはいえ、遅延評価を行うクラスを実装するのは大変  そこで、yieldですよ。 foreach (var item in collection) ココに書ける 十分条件
  18. 18.  yield ◦ yeild return / yield break (C#) ◦ Iterator / Yeild (VB.NET) ◦ 列挙可能型を生成するためのシンタックスシュガー  yieldの動作を見てみよう ◦ ハンズオン ◦ 時間があったらILSpyしてみる
  19. 19. public static IEnumerable<int> GetNaturalNumber() { int i = 0; while (true) { yield return ++i; } } public static IEnumerable<int> GetFibonacchiNumber() { int a = 1; int b = 1; while (true) { yield return b; var temp = a; a = b; b = a + temp; } }
  20. 20. Public Iterator Function GetNaturalNumber() As IEnumerable(Of Integer) Dim i As Integer = 0 While True i = i + 1 Yield i End While End Function Public Iterator Function GetFibonacchi() As IEnumerable(Of Integer) Dim a = 1 Dim b = 1 While True Yield b Dim temp = a a = b b += temp End While End Function
  21. 21. public static int Problem1(int limit) { int sum = 0; foreach (var i in GetNaturalNumber()) { if (i < limit) { if (i % 3 == 0 || i % 5 == 0) { sum += i; } } else { break; } } return sum; } 数列生成 終了条件 抽出条件 合計処理
  22. 22. public static int Problem2(int limit) { int sum = 0; foreach (var i in GetFibonacchiNumber()) { if (i < limit) { if (i % 2 == 0) { sum += i; } } else { break; } } return sum; } 数列生成 終了条件 抽出条件 合計処理
  23. 23.  終了条件、抽出条件も分離してみる ◦ 戻り値の型は、数列生成同様IEnumerable<T> ◦ 引数は?  数列と条件を渡したい  条件って何型? ◦ intを引数に取り、boolを返すメソッド型 ◦ つまりラムダ式を使う
  24. 24.  メソッドを簡易的に定義できる仕組み  古くは ◦ デリゲート(C#1.0) ◦ 匿名メソッド(C#2.0)  引数の型と数、戻り値の型がわかればOK ◦ ここでは、Func<int,bool>を  いろいろラムダ式を書いてみよう ◦ ハンズオン ◦ 省略出来る部分の確認
  25. 25. 3か5で割り切れる  外側のMoveNextが、内 側のMoveNextを要求す る。  内側のCurrentの戻りに よって、外側MoveNext でTrueを返すか、False を返すかを決定する  全てが IEnumereable<T>なの で、いくつでも入れ子に することができる。 1000未満 自然数 MoveNext MoveNext MoveNext Current Current Current
  26. 26.  クラスのメソッドを擬似的に後から追加する仕組 み  何が嬉しい? ◦ コードの記述順が処理順になる。 ◦ インテリセンスの恩恵に預かれる。
  27. 27. public static int Problem1(int limit) { return GetNaturalNumber() .TakeWhile(i => i < limit) .Where(i => i % 3 == 0 || i % 5 == 0) .Sum(); } public static int Problem2(int limit) { return GetFibonacchiNumber() .TakeWhile(i => i < limit) .Where(i => i % 2 == 0) .Sum(); }
  28. 28. Public Function Problem1(ByVal limit As Integer) As Integer Return GetNaturalNumber(). TakeWhile(Function(i) i < limit). Where(Function(i) i Mod 3 = 0 OrElse i Mod 5 = 0). Sum() End Function Public Function Problem2(ByVal limit As Integer) As Integer Return GetFibonacchi(). TakeWhile(Function(i) i < limit). Where(Function(i) i Mod 2). Sum() End Function
  29. 29.  当然ながら、この辺のメソッドは、あらかじめ用 意されています。  System.Linq名前空間を参照しましょう。 ◦ TakeWhile ◦ Where ◦ Sum
  30. 30.  いつでもLINQが最適とは限らない ◦ コード上には現れないが、裏ではループが回っている ◦ ループしないで済む場合は、それで。 public static int Problem1(int limit) { Func<int, int> func = i => { int count = (limit - 1) / i; return (count + 1) * count / 2 * i; }; return func(3) + func(5) - func(15); }
  31. 31.  匿名型 ◦ あらかじめ明示的に型を定義すること無く、読取専用プ ロパティーを  型推論 ◦ 変数宣言の時、型情報を書かなくても、代入する値から 変数の型を推測し決定してくれる

×