x + y

ラムダの回
2011/01/12
1
担当:くま
PochiNet
ラムダとは


C#3.0(Visual Studioだと2008)にて誕生
delegateやLINQをシンプルに記述するため
に作られた言語仕様
2
PochiNet
分かりやすい例
■匿名メソッド
static void Main() {
var dataSource = Enumerable.Range(1, 100);
var query = dataSource.Where(delegate(int i)
{
return i % 13 == 0;
});
foreach (var num in query) { Console.WriteLine(num); }
}
■ラムダ
static void Main() {
var dataSource = Enumerable.Range(1, 100);
var query = dataSource.Where(i => i % 13 == 0);
foreach (var num in query) { Console.WriteLine(num); }
}
3
PochiNet
とりあえず文法から

基本はラムダ演算子「=>」

左辺 => 右辺:左辺を右辺に入力 と読む
(x, y) => x + y は、xとyをx+yに入力と読めばよい

英語だと「=>」は「goes to」って読む

(引数)=>
{実行内容}
4
PochiNet
匿名メソッドからラムダへ

匿名メソッド : delegate(int x, int y) { return x + y; }

ラムダ : (x, y) => x+y

違い
–
–
–
–
–
キーワード(delegateとreturn)が消えた
引数の型指定(int)が消えた
記号(中カッコ({、})と文末のセミコロン(;)が消えた
「=>」の2文字が増えた
トータルで25文字減!
5
PochiNet
匿名メソッドからラムダへ詳細

delegate(int x, int y) { return x + y; }
(x, y) => x+y

詳細

–
–
–
–
delegate → 「=>」 に置き換え
return → ラムダは「式」なので returnがいらない
{、}と; → 「式」だからいらない
引数の型指定 → delegateで宣言されているから分かっている
6
PochiNet
まとめて見てみる
7
PochiNet
文法をちょっと掘り下げる ~左辺~


左辺はdelegateとして呼び出されるメソッ
ドのパラメータ(=入力パラメータ)
パラメータによる書き方の違い
– () => 右辺
– x => 右辺
– (x, y) => 右辺
//パラメータなし
//パラメータ1つ
//パラメータ2つ
8
PochiNet
文法をちょっと掘り下げる ~右辺~

右辺には式か文

式(expression)
※末尾にセミコロンなし
– (x , y) => x + y
– (sender, e) => Console.WriteLine(“式”)

文(statement)
※{}で囲んで式にはコロンをつける
– (sender, e) =>
{
int count = 3;
string msg = String.Format(“{0}つの文です。”, count);
MessageBox.Show(msg);
};
9
PochiNet
掘り下げた状態でちょっと見てみる

今回のサンプルはこれ
\trunk\Source\Samples\PochiNetSamples\PochiNetSamples.sln
\Lambda.proj

ここのリポジトリに入ってます
http://cl106927e5.aspac.local:8080/svn/PochiNet

色んな書き方ができます
– 01文法 参照
10
PochiNet
文法ばっかりだとアレなので



ラムダ式とは名前のないメソッド
生成結果(=ラムダ式中身)はそのままデ
リゲート型の変数や引数に入れて使う
つまり、呼び出しは、名前ではなく、デリ
ゲート型の変数や引数などを経由して行う
11
PochiNet
何をいっているかというと

とりあえずソースをみてみる
– 02ラムダとは参照
– デリゲートであるMyAction型の変数actionを経由して呼び
出しを行っている

ラムダ式を使わないとこんな感じ
– 式の部分を別メソッドとしてもう1つ定義が必要
12
PochiNet
ActionやFunctionを使うと


ラムダからちょい外れるけど、Actionや
Functionを使うと宣言がいらない
欠点
1. 3.5より前の環境で動かない
2. 個別に宣言した方が用途が明確

利点
1. より見やすくなる
13
PochiNet
ラムダ式の利点

短くなることよりも上位スコープにアクセ
スできること
– 03ラムダ利点参照
– 02ラムダとは のラムダを使わないクラスと比べる

利点
1. 引数地獄に陥らない
2. 少数のdelegate宣言で足りる
14
PochiNet
気をつけること

キャプチャされる変数
– 03ラムダ利点の、気をつけるべきこと参照

延命措置がとられる
– CreateMethodの変数Messageはreturn後も残る
– ラムダで使用されている場合、ラムダの寿命まで残る
※正確には、ラムダ式がガベージされるまで

要は変数の使い方に気をつけよ!
15
PochiNet
気をつけないとどうなるか?

あんまり考えなかったときの例
– 04変数のキャプチャ参照

ForとForeachで異なる場合
– For文では0と1を返したはずなのに忘れてる
– Foreachではちゃんと覚えてる

ForとForeachで同じになる場合
– int j はLoop毎にインスタンスが作られる
16
PochiNet
結局便利なの?

便利な使い方をみてみる
– 05素敵さを体感/06素敵さを体感 参照

違い
1. 継承がなくなり、クラスが2つ減った
2. 抽象メソッドのSayMyNameがDelegateになった
3. 名前を保存するフィールドの宣言がなくなった
17
PochiNet
良い?悪い?

利点
1. ソースがスッキリ
2. 名前で参照できなくなったから守られる

欠点
1. 他のメソッドから参照できない
※そのメソッドもラムダ式として書けば使える
2. クラスに属するメソッドなのに、thisが使えない
※変数キャプチャをうまく使う

適材適所で!
18
PochiNet
気をつけること2

オーバーロードの自動解決
– 07気をつけること2 参照

ラムダ式は、より適していると思われるも
のを勝手に呼ぶ
19
PochiNet
その他、特徴など

式ツリーが使える

式ツリーとは?
– 式ツリーは3.5からの新機能
– 実行中に、式をオブジェクトのツリーとして構築し、コン
パイルと実行ができる

主にLINQで使うので、またの機会に!
20
PochiNet
まとめ

ラムダは色々簡単にかけるようになった

ラムダは簡単に書くためだけではないのだ

真価を発揮するのはLINQにてのもよう
21
PochiNet
参考ページ

[完全版]究極のC#プログラミング
Chapter6 ラムダ式
http://www.atmarkit.co.jp/fdotnet/extremecs/extremecs_06/extremecs_06_01.html

C#3.0入門
第1回 ラムダ式
http://www.atmarkit.co.jp/fdotnet/csharp30/csharp30_01/csharp30_01_01.html

MSDN
ラムダ式
http://msdn.microsoft.com/ja-jp/library/bb531253.aspx
22
PochiNet
次!

きっと次はLINQがいいと思う
23
PochiNet