「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>.NET開発]]

* 目次 [#v9445796]
#contents

*概要 [#g9d0b931]
ラムダ式っておじさん達にはユースケースがよく解りませんでしたが、

Java 8でもラムダ式がサポートされたようなので、私を含めて、
>「そろそろ、ラムダ式をちゃんと覚えよう。」

という人向けのコンテンツを書いてみました。

*ラムダ式 [#o8196989]

**進化 [#rc14651d]
おじさん達の知識で振り返って分析してみると、~
中水準言語のC言語の関数ポインタから、

高水準言語の.NET言語(C#、VB)で、~
-デリゲート
-匿名関数
-ラムダ式

と進化してきていることぐらいは解る(?)と思います。

これを見ると、

-デリゲート~ラムダ式の歴史を辿って | もりひろゆきの日々是勉強~
http://moriblog.kit-eng.com/?p=975

厳密には、
厳密には、以下のように進化してきています。

-デリゲート(C# 1.0)~
***デリゲート(C# 1.0) [#wfd6d933]
同じシグネチャを持つメソッドを格納するための変数を宣言し、それを利用できる。

-デリゲート(C# 2.0)~
***デリゲート(C# 2.0) [#z30d6b1d]
デリゲートの代入時にインスタンス生成(new デリゲート名)を省略できる。

-匿名メソッド・匿名関数(C# 2.0)~
***匿名メソッド・匿名関数(C# 2.0) [#s603d78e]
delegate構文を用いて「メソッド名を持たない処理」を記述できる。

-定義済みデリゲート型(共通デリゲート型)(C# 3.0/.NET Framework 3.5)~
ジェネリックの機能を用いて、3種類のデリゲートが定義され、~
-イベント・ハンドラの例
 // Create a handler for a click event.
 button1.Click += delegate(System.Object o, System.EventArgs e)
                    { System.Windows.Forms.MessageBox.Show("Click!"); };

-スレッド関数の例
 System.Threading.Thread t1 = new System.Threading.Thread
   (delegate()
     {
         System.Console.Write("Hello, ");
         System.Console.WriteLine("World!");
     });
 t1.Start();

***定義済みデリゲート型(C# 3.0) [#s78fd4f6]
-定義済みデリゲート型(共通デリゲート型)(C# 3.0/.NET Framework 3.5)

-ジェネリックの機能を用いて、3種類のデリゲートが定義され、~
「delegateキーワードを使ったデリゲート宣言」を省略できる。

--戻り値のない定義済みデリゲートのAction~
最新の.NET 4.5では引数の数が最大16まであるデリゲートが定義されている。

--戻り値を持つ定義済みデリゲートのFunc~
最新の.NET 4.5では引数の数が最大16まであるデリゲートが定義されている。

--論理型のも戻り値を持つ定義済みデリゲートのPredicate

-ラムダ式(C# 3.0)~
--デリゲート型/式ツリー(ExpressionTree)を作成するために使用できる匿名関数
--ラムダ演算子(=>) を用いて左辺にパラメタ、右辺に式やコードブロックを置く
***ラムダ式(C# 3.0) [#g0b13ee0]
[[定義済みデリゲート型>#s78fd4f6]]とセットで使用する。
-デリゲート型/式ツリー(ExpressionTree)を作成するために使用できる匿名関数
-ラムダ演算子(=>) を用いて左辺にパラメタ、右辺に式やコードブロックを置く

というふうに進化してきています。

**用途 [#p0922a94]
ラムダ式は、

-[[LINQ]]クエリ式や
-デリゲートと多用する新しいAPIの

delegateを必要とするメソッドを~
実行しやすくするために生まれてきたようです。

-参考

--C#ラムダ式 基礎文法最速マスター - @IT~
http://www.atmarkit.co.jp/fdotnet/rapidmaster/rapidmaster_01/rapidmaster_01.html
>C#言語のラムダ式(lambda expressions)とは、~
デリゲート(delegate)や、メソッド・ベースの[[LINQ]]文の(例えば)~
WhereメソッドやSelectメソッドなどの引数をシンプルに記述するために、~
C# 3.0(=Visual C# 2008)以降で導入された言語仕様である。

これについては、以下の[[利用例>#mea2384e]]を引き合いに出して説明したいと思います。

*ポイント [#kfb99b40]

**文法 [#a6c0a0d3]

***式形式 [#q3f16b1c]
-引数がない場合
 () => {
   (式形式の実装)
 }

-引数が一つの場合
 (引数名) => {
   (式形式の実装)
 }

-引数が複数の場合
 (引数名1,引数名2,引数名3, ...) => {
   (式形式の実装)
 }

***ステートメント形式 [#tfa1d0b5]
-引数がない場合
 () => (ステートメント形式の実装)

-引数が一つの場合
 引数名 => (ステートメント形式の実装);

-引数が複数の場合
 (引数名1,引数名2,引数名3, ...) => (ステートメント形式の実装)

**仮引数と実引数 [#h74c9aea]

***仮引数(parameter) [#k7796ec6]
以下の場合、仮引数(parameter)を指定する。

-デリゲートをメソッドの引数として渡す場合で、
-上記のデリゲートの引数をメソッドが内部から指定する場合

このため、一瞬どこから現れたのか不明な変数に見える。

LINQのメソッド ベースのクエリ構文などで使用される。

***実引数(argument) [#hdb9e50c]
上記以外の場合は、実引数を指定する。

**スコープ [#td9e44e5]
ラムダ式では、そのスコープの外側にある~
変数やメソッドを利用でき引数の肥大化が防げる。

(これは、匿名メソッド・匿名関数でも同じ)

**デリゲートの型 [#s424189d]
このため、T1-T16までのデリゲートが用意されている。
このため(ラムダ式で利用可能なメソッドを定義するために)、~
ActionとFuncの、T1-T16までのデリゲートが用意されている。

-参考
--Action(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) デリゲート (System)~
https://msdn.microsoft.com/ja-jp/library/dd402872.aspx
--Func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult) デリゲート (System)~
https://msdn.microsoft.com/ja-jp/library/dd402862.aspx

*利用例 [#mea2384e]
ということで、引数をラムダ式にすることで、~

>delegateを必要とするメソッドを実行しやすくする。

ようなシーンが、ラムダ式の代表的な利用ケースではないか?と思います。

-[C#][ラムダ式][LINQ][式木] 匿名メソッドとラムダ式の違い~
(プログラミング C# - 翔ソフトウェア (Sho's))~
http://blog.shos.info/archives/2012/11/clinqexpression.html
>ラムダ式を使った方が、型推論の恩恵を存分に受けられ、書き方がぐっとシンプルになる。

-これは、[[LINQ]]のメソッド ベースのクエリ構文で使用されています。~
SELECTやWHEHE句などの動作のカスタマイズにdelegateを使用可能ですが、~
これを一般的にはラムダ式を使用して記述します。
 var query5 = RowList
   .Where(p => p.Field<int>("年度") == 2012)
   .Select(p => new
   {
     年度 = p.Field<int>("年度"),
     種別 = p.Field<int>("種別"),
     生年度 = p.Field<int>("生年度"),
     平均人員2 = p.Field<int>("平均人員") / 12,
     支給年金額 = p.Field<int>("支給年金額")
   });

-その他、任意の変数に編集処理を渡すことができる。

--ASP.NET MVC で WebGrid を最大限に活用する - MSDN~
https://msdn.microsoft.com/ja-jp/magazine/hh288075.aspx
>新しい WebGrid<T> 実装では、format パラメーターに~
Func<T, object> を受け取る新しい Column メソッドを追加しています。~
 grid.Column(
   columnName: "EmailAddress", 
   header: "Email Address", 
   format: item => Html.EmailLink(
     (string)item.EmailAddress, 
     (string)item.EmailAddress, 
     ""
   ), 
   canSort: false
 )

*参考 [#h35da447]

**Qiita [#sf4f5412]
-関数型プログラミングって何、ラムダってなんだよ~
http://qiita.com/lrf141/items/98ffbeaee42d30cca4dc
-【LINQの前に】ラムダ式?デリゲート?Func<T, TResult>?な人へのまとめ【知ってほしい】~
https://qiita.com/RyotaMurohoshi/items/740151bd772889cf07de

**C# プログラミング ガイド [#s00748f6]
-匿名メソッド~
https://msdn.microsoft.com/ja-jp/library/0yw3tz5k.aspx
-ラムダ式~
https://msdn.microsoft.com/ja-jp/library/bb397687.aspx
--方法: クエリでラムダ式を使用する~
https://msdn.microsoft.com/ja-jp/library/bb397675.aspx
--方法: LINQ 以外でラムダ式を使用する~
https://msdn.microsoft.com/ja-jp/library/bb383984.aspx

**@IT [#ccee0547]
-C#&VB ラムダ式 基礎文法★チートシート~
http://www.atmarkit.co.jp/fdotnet/chushin/cheatsheet_01/cheatsheet_01_01.html
--C#ラムダ式 基礎文法最速マスター~
http://www.atmarkit.co.jp/fdotnet/rapidmaster/rapidmaster_01/rapidmaster_01.html
--VBラムダ式 基礎文法最速マスター~
http://www.atmarkit.co.jp/fdotnet/rapidmaster/rapidmaster_02/rapidmaster_02.html

**[[LINQ]] [#n54151cf]
-Chapter16 LINQとメソッド構文 - @IT~
http://www.atmarkit.co.jp/fdotnet/extremecs/extremecs_16/extremecs_16_01.html
-Enumerable メソッド (System.Linq)~
https://msdn.microsoft.com/ja-jp/library/system.linq.enumerable_methods.aspx

----
Tags: [[:プログラミング]], [[:.NET開発]]


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS