ラムダ式

文法

「=>」: GoesTo(ゴーズ・トゥ)
意味 : 左辺の変数を入力値として、右辺の式を実行する
パラメータがない場合
() => 右辺
パラメータが1つの場合
prm => 右辺
パラメータが2つ以上の場合
(prm1, prm2) => 右辺
パラメータの型指定
(int prm) => 右辺
左辺 => 式
左辺 => { 式; 式; 式; }

例(1)イベント登録

通常文法
private event EventHandler myEvent;
myEvent += new EventHandler(this.myFunction);
private void myFunction(object sender, EventArgs e)
{
  Console.WriteLine("通常メソッド");
}

匿名メソッド
myEvent += delegate(object mySender, EventArgs myE) {
  Console.WriteLine("匿名メソッド");
};

ラムダ式
myEvent += (mySender, myE) => Console.WriteLine("ラムダ式");

↑ イベントを発生させる
myEvent(sender: this, e: new EventArgs());

例(2)Delegate

delegate void MyDelegator1(string prm);
delegate void MyDelegator2(string prm1, string prm2);
static void Main(string[] args)
{
 式形式ラムダ
 MyDelegator1 m1 = (n) => Console.WriteLine(n);
 
 m1(@"aaa");
 
 
 ステートメント形式ラムダ
 MyDelegator2 m2 = (n, o) =>
 {
  for (int i = 0; i < 5;i++ )
  {
   Console.WriteLine(n);
   Console.WriteLine(o);    
  }
  return;
  Console.WriteLine(@"aaa");

 };
 
 m2(@"aaa", @"bbb");
}

定義済みDelegate:Action

戻り値:void 引数:無し
delegate void Action(); という宣言が不要
Action act1 = () =>
{
 Console.WriteLine(@"aaa");
};
act1();

戻り値:void 引数:n個
delegate void Action(string prm); という宣言が不要
Action<string> act2 = (string prm) =>
{
 Console.WriteLine(prm);
};
act2(@"aaa");

定義済みDelegate:Func

戻り値:string 引数:無し
delegate string Func(); という宣言が不要
Func<string> fnc1 = () =>
{
 return @"bbb";
};
string ret = fnc1();

戻り値:string 引数:n個
delegate string Func(string prm); という宣言が不要
Func<string, string> fnc2 = (string prm) =>
{
 return prm + prm;
};
string ret = fnc2(@"bbb");

定義済みDelegate:Predicate

戻り値:bool固定。 引数:n個 ※引数0個は無し
delegate bool Predicate(int prm); という宣言が不要
Predicate<int> pred = (int i) =>
{
 return i > 0;
};
bool ret = pred(5);

例(3)LINQ

通常文法
var dataSource = Enumerable.Range(start: 0, count: 100);
var query = dataSource.Where(WhereMethod);
private bool WhereMethod(int i)
{
  return i % 13 == 0;
  13で割り切れる=trueを返す
  13で割り切れない=falseを返す
}

匿名メソッド
query = dataSource.Where(delegate(int i)
{
  return i % 13 == 0;
  13で割り切れる=trueを返す
  13で割り切れない=falseを返す
});

ラムダ式
query = dataSource.Where(i => i % 13 == 0);
13で割り切れる=trueの数値だけを抽出する

例(4)delegateを利用した共通処理

※旧プログラム
private void button1_Click(object sender, EventArgs e)
{
 var obj = ((System.Windows.Forms.Control)(sender));
 CommonWork(obj);
}
private void button2_Click(object sender, EventArgs e)
{
 var obj = ((System.Windows.Forms.Control)(sender));
 CommonWork(obj);
}
private void CommonWork(System.Windows.Forms.Control obj)
{
 共通処理
 
 ボタンイベントからの引数に応じて処理を分岐
 if (obj == this.button1)
 {
  個別処理
 }
 else if (obj == this.button2)
 {
  個別処理
 }
 
 共通処理
}

※delegate利用
void button1_Click(object sender, EventArgs e)
{
 Action myAction = delegate
 {
  共通関数で実行する個別処理
 };
 
 CommonWork(myAction);
}
void button2_Click(object sender, EventArgs e)
{
 Action myAction = delegate
 {
  共通関数で実行する個別処理
 };
 
 CommonWork(myAction);
}
void CommonWork(Action myAction)
{
 共通処理
 
 引数に渡されたdelegateを実行
 処理を分岐する必要無し
 myAction();
 
 共通処理
}

例(5)サブルーチン短略化

何度も呼び出さないサブルーチン
private static string sub1(string a, string b, string c)
{
 return a + b + c;
}
static void Main(string[] args)
{

 string x = @"A";
 string y = @"B";
 
 ① 従来の方法(外部にサブルーチンがあり可読性が悪い)
 var ret1 = sub1(x, y, @"C");
 
 ② 定義済みdelegate & ラムダ式の利用
 Func sub2 = (string a, string b, string c) =>
 {
  return a + b + c;
 };
 var ret2 = sub2(x, y, @"C");
 
 ③ ↑を短く
 Func sub3 = (string a, string b, string c) => a + b + c;
 var ret3 = sub3(x, y, @"C");
 
 ④ x, y を参照しているだけでサブルーチンに渡す必要がないので省略
 Func sub4 = (string a) => x + y + a;
 var ret4 = sub4(@"C");
}

例(6)連番

string[] myStr = { "Aさん", null, "Bさん", null, "Cさん" };
匿名クラスの利用
foreach (var elm in myStr.Select((s, i) => new { myElm = s, mySeq = i }))
{
 Console.WriteLine(elm.myElm + ":" + elm.mySeq);
}

Aさん:0
:1
Bさん:2
:3
Cさん:4
※iにはindexが入る

↓ 省略形
foreach (var elm in myStr.Select((s, i) => new { s, i }))
{
 Console.WriteLine(elm.s + ":" + elm.i);
}

foreach (var elm in myStr.where(n => n != null).Select((s, i) => new { s, i }))
{
 Console.WriteLine(elm.s + ":" + elm.i);
}

Aさん:0
Bさん:1
Cさん:2
※iにはindexが入る

例(7)配列の初期化

int[] ary = { 1, 2, 3, 4, 5 };
ary = ary.Where(a => a != 3).ToArray();
ary:1 2 4 5

例(7)ソート

class Item
{
 public int myInt { get; set; }
 public Item(int prm)
 {
  this.myInt = prm;
 }
}

class MyCompare : System.Collections.IComparer
{
 public int Compare(object a, object b)
 {
  return ((Item)a).myInt – ((Item)b).myInt;
 }
}

class Program
{
 static void Main(string[] args)
 {

  Item[] ary = { new Item(prm: 5), new Item(prm: 0), new Item(prm: 10) };
  Array.Sort(ary, new MyCompare());
  → 0 5 10
 }
}

class Item
{
 public int myInt { get; set; }
 public Item(int prm)
 {
  this.myInt = prm;
 }
}

static void Main(string[] args)
{

 Item[] ary = { new Item(prm: 5), new Item(prm: 0), new Item(prm: 10) };
 Array.Sort(ary, (x, y) => x.myInt – y.myInt );
 → 0 5 10
}