ラムダ式と言えばメソッド定義で使うことが多いです。
LINQでラムダ式で匿名メソッド
int[] numbers = { 1, 7, 0, 4, 3, 7, 9, 2, 5, 8 };
int count = numbers.Count(n => n > 4);
Console.WriteLine($"4を超える数は{count}つです。"); // 4を超える数は5つです。
ラムダ式でインスタンスメソッド定義
class Greeter {
public void Greeting() =>
Console.WriteLine("Hello world!");
}
var greeter = new Greeter();
greeter.Greeting(); // Hello world!
ラムダ式は読みやすく書きやすいので好きです。
調べていたらゲッターやインデクサでも使うことができることを知りました。
ゲッターをラムダ式で定義する
class Product {
public double Price { get; set; }
// ↓ ラムダ式で読み取り専用プロパティを定義
public double IncludeTaxPrice => Price * 1.08;
}
var daifuku = new Product { Price = 100 };
Console.WriteLine($"税込価格は{daifuku.IncludeTaxPrice}です");
// 税込価格は108です
ラムダ式によるメソッド定義によく似ていますが、
プロパティ名の後に()
がありません。
- 副作用を起こす処理
- 重い処理
はゲッターでなくメソッドにするとよいと思います。
従来の書き方では{{}}
で囲む必要があり、get
やreturn
などのノイズが多いです。
public double IncludeTaxPrice { get { return Price * 1.08; } }
また、return
の代わりにget
の本体をラムダ式にすることもできます。
IncludeTaxPrice { get => Price * 1.08; }
インデクサをラムダ式で定義する
インデクサでもラムダ式が使えます。
ゲッターと同様に読み取り専用の場合、特に読みやすくなります。
本棚クラス
class Bookshelf {
readonly IList<Book> books = new List<Book>();
// ↓ 読み取り専用のインデクサがスッキリかける
public Book this[int index] => books[index];
public void Add(Book book) => books.Add(book);
}
class Book {
public string Title { get; }
public Book(string title) => Title = title;
}
var bookshelf = new Bookshelf();
bookshelf.Add(new Book(title:"幼年期の終り"));
bookshelf.Add(new Book(title:"1984年"));
bookshelf.Add(new Book(title:"アンドロイドは電気羊の夢を見るか"));
// インデクサ経由で Book オブジェクトを取り出す
var book = myshelf[1];
Console.WriteLine(book.Title); // 1984年
余談
コンストラクタもラムダ式で定義することができます。
class Logger {
readonly TextWriter writer;
// コンストラクタでプライベートフィールドを初期化する
public Logger(TextWriter writer) => this.writer = writer;
public void WriteLog(string text) => writer.WriteLine(text);
}
var consoleLogger = new Logger(writer: Console.Out);
consoleLogger.WriteLog("コンソールに出力");
using (var writer = new StreamWriter("log.txt")) {
var fileLogger = new Logger(writer);
fileLogger.WriteLog("ファイル書き込み");
}
ただ、コンストラクタはゲッターやメソッドと見間違ったり、
設計中に引数が増減する機会も多く書き直す手間を考えると個人的にブロックで書く派です。
return
もないので{}
と=>
の違いくらいしかないです。
プロパティもラムダ式で書けますが、自動実装プロパティのほうが簡単でしょうか。
class Circle {
public double Radius { get; set; }
/*
* ラムダ式で書くとこれだけ必要...
* double radis;
* public double Radius { get => radis; set => radis = value; }
*/
public double Area() => Radius * Radius * Math.PI;
}