C#でラムダ式を理解する

# 1. はじめに
* 見よう見まねで書いているラムダ式を最初から理解したい
* => (ラムダ演算子：ゴーズ・トゥー）の意味を理解したい


# 2. 開発環境
* Visual Studio 2022
* .NET6
* Windows10

# 3. ラムダ式を理解する前に
## 3.1. ラムダ式なし
* この式を徐々にラムダ式に変えていく
```csharp:
var values = new string[] { "A", "BB", "CCC", "DDDDD", "EEEEE" };

var result = new List<string>();
foreach (var val in values)
{
	if (val.Length >= 3)
	{
		result.Add(val)
	}
}

Console.WriteLine(string.Join(",", result);
```

## 3.2. ラムダ式なし：共通関数
* 共通関数を作成する
```csharp:
var result = GetValues(values);
Console.WriteLine(string.Join(",", result);

private string[] GetValues(String[] values)
{
	var result = new List<string>();
	foreach (var val in values)
	{
		if (val.Length >= 3)
		{
			result.Add(val)
		}
	}

	return result.ToArray();
}
```

## 3.3. ラムダ式なし：共通関数2
* 共通関数に引数を追加する
```csharp:
var result = GetValues(values, 3);
Console.WriteLine(string.Join(",", result);

private string[] GetValues(String[] values, int len)
{
	var result = new List<string>();
	foreach (var val in values)
	{
		if (val.Length >= len)
		{
			result.Add(val)
		}
	}

	return result.ToArray();
}
```

## 3.4. ラムダ式なし：デリゲート
* デリゲートを定義して式をパラメータに渡す
```csharp:
var result = GetValues(values, Shiki);
Console.WriteLine(string.Join(",", result);

delegate bool LenCheck(string value);

private bool Shiki(string value)
{
	return str.Length >= 3;	
}

private string[] GetValues(String[] values, LenCheck lenCheck)
{
	var result = new List<string>();
	foreach (var val in values)
	{
		if (lenCheck(val))
		{
			result.Add(val)
		}
	}

	return result.ToArray();
}
```

## 3.5. ラムダ式なし：匿名メソッド
* デリゲートに匿名メソッドを渡す
```csharp:
var result = GetValues(
	values, 
	delegate (string s)
	{
		 return s.Length == 3;
	}
);
Console.WriteLine(string.Join(",", result);

delegate bool LenCheck(string value);

private string[] GetValues(String[] values, LenCheck lenCheck)
{
	var result = new List<string>();
	foreach (var val in values)
	{
		if (lenCheck(val))
		{
			result.Add(val)
		}
	}

	return result.ToArray();
}
```

## 3.6. ラムダ式なし：Predicate
* デリゲートをPredicateに書き換える
```csharp:
var result = GetValues(
	values, 
	delegate (string s)
	{
		 return s.Length == 3;
	}
);

Console.WriteLine(string.Join(",", result);

delegate bool LenCheck(string value);

private string[] GetValues(String[] values, Predicate<string> predicate)
{
	var result = new List<string>();
	foreach (var val in values)
	{
		if (predicate(val))
		{
			result.Add(val)
		}
	}

	return result.ToArray();
}
```

# 4. ラムダ式の文法
## 4.1. C#の遍歴
* C# 1.0 delagate
* C# 2.0 匿名メソッド、Predicate,ジェネリック
* C# 3.0 ラムダ式、Linq
* C# 4.0以降 リフレクション、Task, async, awaitなど

## 4.2. ラムダ式の文法
```csharp:
// ラムダ式なし
delegate(string s)
{
	return s.Length==3;
}

// ラムダ式あり
s=> s.Length==5
```
* => ラムダ演算子（ゴーズ・トゥ）の書き方
    * 左辺：パラメータ
    * 右辺：式または文
        * 右辺が式のみの場合はreturnを書かなくてよい
        * 右辺が分の場合は{},return,;が必要

## 4.3. パラメータ別の書き方
* パメータなしの場合
    * ```()=>Console.WriteLine("XXX")```
* パラメータ1つの場合
    *  ```s=> s.Length==5 ```
* パラメータが複数の場合
    *  ```(a,len) => a.Length==5+len ```
```csharp:
// パラメータが2つの場合
(a,len) =>
{
	if(a[0]) == 'E')
	{
		return a.Length > len;
	}
	return false;
}

// パラメータが1つの場合
var values = new string[] { "A", "BB", "CCC", "DDDDD", "EEEEE" };

var result = GetValues(
	values, 
	value => value.Length == 3
);

Console.WriteLine(string.Join(",", result);

private string[] GetValues(String[] values, Predicate<string> predicate)
{
	var result = new List<string>();
	foreach (var val in values)
	{
		if (predicate(val))
		{
			result.Add(val)
		}
	}

	return result.ToArray();
}
```

## 4.4. Func, Actionの書き方
* Func: 戻り値がある場合
* Ation: 戻り値がない場合
```csharp:
// Funcの書き方
delegate bool LenCheck(string value; int len);
Func<string, int, bool> lenCheck // 最後が戻り値

// Actionの書き方
delegate void MyCheck(string value);
Action<string>
```

## 4.5. コレクションの書き方
* IEnumerableで使用できる
    * Where
    * Any
* Listのみ
    * Find
    * FindAll
    * Exist
```csharp:
// コレクション
var values = new string[] { "A", "BB", "CCC", "DDDDD", "EEEEE" };

var result4 = values.Where(x=> x.Contains("B"));
Console.WriteLine("result:" + string.join(",", result4));
// x=> x.Contains("B").ToList()にすると即時実行できる

var result5 = values.Any(x=> x.Contains("B"));
Console.WriteLine("result:" + string.join(",", result5));

// Listしか使用できない
// Where + Firstと同じ
var result1 = values.Find(x=> x.Contains("B"));
Console.WriteLine("result:" + string.join(",", result1));

// Listしか使用できない
// Whereと同じ
var result2 = values.FindAll(x=> x.Contains("B"));
Console.WriteLine("result:" + string.join(",", result2));

// Listしか使用できない
// Anyと同じ
var result3 = values.Exist(x=> x.Contains("B"));
Console.WriteLine("result:" + string.join(",", result3));
```

# 5. 参考文献
https://anderson02.com/cs/lambda/lambda01/