プログラム言語 ラムダ式

文法

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

Delegate

通常文法
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());

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

戻り値無

戻り値: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");

Runnable型 ※引数無し/戻り値無し
Runnable run = () -> { System.out.println("Hello"); };
run.run();

Consumer型 ※引数1つ/戻り値無し
Consumer<String> func = (i) -> { System.out.println(i); };
func.accept("aaa");

戻り値有

戻り値: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");

使用例:何度も呼び出さないサブルーチン
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");
}

Function型 ※引数1つ/戻り値1つ
Function<Integer, Integer> func = (i) -> { return i*10; };
int ret = func.apply(5);

Supplier型 ※引数無し/戻り値1つ
Supplier<String> func = () -> { return "return"; };
String ret = func.get();

UnaryOperator型 ※引数1つ/戻り値1つで引数、戻り値が同型
UnaryOperator<Integer> func = (i) -> { return i*10; };
int ret = func.apply(5);

戻り値=Bool型、引数有

戻り値:bool固定。 引数:n個 ※引数0個は無し
delegate bool Predicate(int prm); という宣言が不要
Predicate<int> pred = (int i) =>
{
 return i > 0;
};
bool ret = pred(5);
Predicate型 ※引数1つ/戻り値Bool型
Predicate<Integer> func = (i) -> { return i % 3 == 0; };
Boolean ret = func.test(3); // true

関数型インターフェース/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)
 {
  個別処理
 }
 
 共通処理
}
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();
 
 共通処理
}
// Runnable型のメソッド定義
Runnable func1 = () -> { System.out.println("AAA");};
Runnable func2 = () -> { System.out.println("BBB");};

// 通常実行
func1.run();
func2.run();

Runnable型のメソッドを渡す
method(func1);
method(func2);

// 引数がRunnable型のメソッド
private void method(Runnable func) {

 共通処理
 
 func.run();
 
 共通処理
 
 return;
}

ソート

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
}