狠狠撸

狠狠撸Share a Scribd company logo
road to Linqulien
? 米田 大介(三十路後半)
? 業務系のSEっポイことしてます。
? C#が好きです。
? でも、今業務ではVB.NETを書いてます。
? LINQが好き
? なので、VBでもLINQがかけるようになりました。
? Room Metroとかに、よくお世話になってます。
? とりあえず
ググる 福岡のアイド
ル?
コッチ
1. とりあえずコード書いてみましょう
2. リファクタリングしてみます。
3. なんと!? LINQがそこに。
最初はLINQなしでね
パチパチパチ
? 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 日本語」で検索!!
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;
}
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
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;
}
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
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;
}
数列生成
終了条件
抽出条件
合計処理
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;
}
数列生成
終了条件
抽出条件
合計処理
? 現状の問題
? 処理が分散して、入り交じっている。
? これを
? 同じ処理はまとめる
? 違う処理は分ける
? なぜ?
? 再利用する
? 組み合わせ爆発を防ぐ
? わかりやすい
? 同じコードは何度も書きたくない
? DRY
? 結果としてコードが短くなる
共通部分は、
メソッドにしたい
小難しい部分は、
ライブラリを呼ぶだけが
いい
? 複雑さは乗数で増えていく。
? 何時、何処で、誰が、何をした。
自然数
フボナッチ
数
1000未満
400万未満
偶数
3か5で
割切れる
合計
平均
素数
先頭の100
個
標準偏差奇数番目
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
? 分けたからわかりやすい
? 自然言語として、わかりやすい単位で分ける
? 适当な范囲で名前を付けられる
? 数列生成部分を分けてみる
? 戻り値の型は?
? List or Array
? あらかじめ必要となる要素数が分かってないと、生成できない。
? じゃ、どうする?
? IEnumerable<T>
? 列挙可能型
? 唯一のメソッドはGetEnumerator()
? MoveNextとCurrentを定義するIEnumerator<T>を返す
? List<T> / T[] 等、全てのコレクションの基底Inte
rface
? foreachで回せる
? 実際に値が必要になるときまで評価を遅延する実装が可
能
? 可能とはいえ、遅延評価を行うクラスを実装するのは大変
? そこで、yieldですよ。
foreach (var item in collection)
ココに書ける
十分条件
? yield
? yeild return / yield break (C#)
? Iterator / Yeild (VB.NET)
? 列挙可能型を生成するためのシンタックスシュガー
? yieldの動作を見てみよう
? ハンズオン
? 時間があったらILSpyしてみる
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;
}
}
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
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;
}
数列生成
終了条件
抽出条件
合計処理
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;
}
数列生成
終了条件
抽出条件
合計処理
? 終了条件、抽出条件も分離してみる
? 戻り値の型は、数列生成同様IEnumerable<T>
? 引数は?
? 数列と条件を渡したい
? 条件って何型?
? intを引数に取り、boolを返すメソッド型
? つまりラムダ式を使う
? メソッドを簡易的に定義できる仕組み
? 古くは
? デリゲート(C#1.0)
? 匿名メソッド(C#2.0)
? 引数の型と数、戻り値の型がわかればOK
? ここでは、Func<int,bool>を
? いろいろラムダ式を書いてみよう
? ハンズオン
? 省略出来る部分の確認
3か5で割り切れる
? 外側のMoveNextが、内
側のMoveNextを要求す
る。
? 内側のCurrentの戻りに
よって、外側MoveNext
でTrueを返すか、False
を返すかを決定する
? 全てが
IEnumereable<T>なの
で、いくつでも入れ子に
することができる。
1000未満
自然数
MoveNext
MoveNext
MoveNext
Current
Current
Current
? クラスのメソッドを擬似的に後から追加する仕組
み
? 何が嬉しい?
? コードの記述順が処理順になる。
? インテリセンスの恩恵に預かれる。
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();
}
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
? 当然ながら、この辺のメソッドは、あらかじめ用
意されています。
? System.Linq名前空間を参照しましょう。
? TakeWhile
? Where
? Sum
? いつでも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);
}
? 匿名型
? あらかじめ明示的に型を定義すること無く、読取専用プ
ロパティーを
? 型推論
? 変数宣言の時、型情報を書かなくても、代入する値から
変数の型を推測し決定してくれる

More Related Content

超尝滨狈蚕入门