C# 3.0からラムダ式を作成出来るようになりました。pythonを使っている人には
おなじみのものですね。
ちなみにpythonの場合は、以下のようにしてラムダ式を作成します。
f = lambda x: x * x f(2)
同じものをC#で書くと以下のようになります。
Func<int, int> f = x => { return x * x; }; Console.WriteLine(f(2));
上記の部分で
x => { return x * x; };
となっている部分がラムダ式です。C# 2.0の場合は以下のように記述していました。
Func<int, int> f = delegate(int x){ return x * x; }; Console.WriteLine(f(2));
ラムダ式は、匿名デリゲートをもう少し簡便に記述できるようになったという雰囲気だと
思うと分かりやすいです。なので、Array.ForEachなどが書きやすくなります。
Array.ForEach(Array.ConvertAll(new[]{"hoge", "hehe", "fuga"}, elem => { return elem.ToUpper(); }), elem => { Console.WriteLine(elem); });
上の例は匿名デリゲートを使用しても同じものが記述できますが、ラムダ式で記述したほうが個人的には見やすいです。
また、ラムダ式を利用することでクロージャー(Closure)を書くことが出来ます。(匿名デリゲートでも出来ますが・・)
Func<int, Func<int, int>> MakeClosure = x => { return y => { return x + y; }; }; Func<int, int> closure = MakeClosure(10); Func<int, int> closure2 = MakeClosure(20); Console.WriteLine(closure(100)); Console.WriteLine(closure2(100));
上記を実行すると、110, 120となります。
ちゃんとクロージャーを作成した際に渡した本来ならスコープ外の値も保持されていますね。(関数閉包)
てことで、以下サンプルです。
// vim:set ts=4 sw=4 et ws is nowrap ft=cs: using System; namespace Gsf.Samples.Tmp{ public class LambdaExpressionSample : IExecutor{ public void Execute(){ // // 普通にラムダ式を作成. // Func<int, int> f = x => { return x * x; }; Console.WriteLine(f(2)); // // Array.ForEachとArray.ConvertAllのデリゲートにラムダ式を指定. // Array.ForEach(Array.ConvertAll(new[]{"hoge", "hehe", "fuga"}, elem => { return elem.ToUpper(); }), elem => { Console.WriteLine(elem); }); // // クロージャーを作成. // Func<int, Func<int, int>> MakeClosure = x => { return y => { return x + y; }; }; Func<int, int> closure = MakeClosure(10); Func<int, int> closure2 = MakeClosure(20); Console.WriteLine(closure(100)); Console.WriteLine(closure2(100)); } } }
ちなみに、ラムダ式や匿名デリゲートでは一旦作成したデリゲートを保持しておく際に
以下のジェネリックデリゲートが良く使われます。
- System.Func
- System.Func
- System.Action
- System.Action(T)
- System.Predicate(T)
上記の内、Funcジェネリックデリゲートは.NET Framework 3.5で登場しました。
System.Core.dll内に存在しています。
また、Func,Actionデリゲートは共に、引数を4つまで受け取れるよう
複数定義されています。