連載
» 2017年07月05日 05時00分 UPDATE

.NET TIPS:構文:メソッドやプロパティをラムダ式で簡潔に実装するには?[C# 6.0/7.0]

C# 6.0/7.0では、ラムダ式を使ってメソッドやプロパティを簡潔に記述できる。短くて読みやすいコードを記述するにはうってつけの方法だ。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

■更新履歴
【2017/07/05】Visual Studio 2017(C# 7.0)の新機能を使う方法を追加しました。
【2016/06/01】初版公開。
本稿は2016/06/01に初版公開された記事を改訂し、C# 7.0の新機能を利用する記述を追加したものです。


対象:Visual Studio 2015(C# 6.0)以降/Visual Studio 2017(C# 7.0)以降


 内容が短いメソッドやプロパティを書くとき、もっと簡潔に書けたらよいのにと思ったことはないだろうか? 読み取り専用のプロパティを大量に書く場合には、特にそうだろう。それがC# 6.0からは、ラムダ式を使って簡潔に書けるようになっているのだ。C# 7.0では、さらに便利になっている。本稿ではその使い方を説明する。

 本稿中、特にバージョンの記述がない機能は、C# 6.0から利用できるものだ。

利用できるラムダ式

 C#のラムダ式には「式」と「ステートメント」の2つの形式があるが、本稿の方法で使えるのは、式形式のラムダ式のみである。

 ステートメント形式、すなわち「=>」演算子の右側に中かっこ(「{」と「}」)を置く形式のラムダ式は使えない。

メソッド

 メソッドの引数の後ろにラムダ式の本体を書く(次のコード)。

// 従来の書き方
public int Twice_oldstyle(int n)
{
  return n * 2;
}

// C# 6.0のラムダ式を使った記述
public int Twice(int n) => n * 2;

ラムダ式を使ったメソッド記述の例
メソッド本体が1行の場合、従来の書き方では(Visual Studioの標準的なインデント方式の場合で)4行になる。それが、ラムダ式を使った記述では1行で済むのだ。

 なお、メソッドが返す型はvoidでも構わない(次のコード)。この場合は、ラムダ式が値を返したとしても無視される。

// C# 6.0
public void Print(string title, string msg)
  => Console.WriteLine($"{title}:{msg}");

// 呼び出し例
Print("タイトル", "メッセージ本文");
// ⇒出力:タイトル:メッセージ本文

ラムダ式を使ったメソッド記述の例
値を返さないメソッド(void型のメソッド)でも、ラムダ式で記述できる。
先頭に「$」を付けた文字列の表記については、「.NET TIPS:日付や時刻を文字列に変換するには?」の補間文字列についての解説を参照。

プロパティ

 C# 6.0では、読み取り専用のプロパティをラムダ式で記述できる(次のコード)。

 ラムダ式が使えてうれしいのは、特にこのプロパティを記述する場面だろう。例えば、WPFアプリやUWPアプリで画面に表示するデータを保持するクラスを書くときに、読み取り専用のプロパティを大量に記述することがある。それは、データを画面表示用の文字列にフォーマットして返すプロパティだ(双方向バインディングならバリューコンバーターを作るべきだが、一方向バインディングならプロパティを追加する方がはるかに実装が簡単である)。

public class Person
{
  // 読み書きする通常のプロパティ
  public string FirstName { get; set; }
  public string LastName { get; set; }

  // 読み取り専用プロパティ:従来の書き方
  public string FullName_oldstyle
  {
    get
    {
      return FirstName + " " + LastName;
    }
  }

  // 読み取り専用プロパティ:ラムダ式で記述
  public string FullName => FirstName + " " + LastName;
}

ラムダ式を使った読み取り専用プロパティの記述例
読み取り専用プロパティのgetter本体が1行の場合、従来の書き方では(Visual Studioの標準的なインデント方式の場合で)7行にもなる。それが、ラムダ式を使った記述では1行で済むのだ。
このようにラムダ式で読み取り専用プロパティを記述するときは、getキーワードは不要である。

 C# 7.0では、通常のプロパティ(読み取りと書き込みの両方を備えたもの)もラムダ式で記述できる(次のコード)。

private DateTime _birthday;

// 読み書きするプロパティ:ラムダ式で記述(C# 7.0)
public DateTime Birthday
{
  get => _birthday;
  set => _birthday = value; // メンバ変数への代入も書ける
}

// 読み書きするプロパティ:ラムダ式で記述(C# 7.0)
public string BirthdayString
{
  get => _birthday.ToString("yyyy/MM/dd");
  set => DateTime.TryParse(value, out _birthday); 
}

ラムダ式を使った通常のプロパティの記述例(C# 7.0)
C# 7.0からは、プロパティのgetter/setterもラムダ式で書けるようになった。
この例のBirthdayプロパティのような単純なgetter/setterでは、自動実装プロパティを使った方が簡潔だ。しかし、BirthdayStringプロパティのようにgetter/setter内に処理を記述する場合は、ラムダ式での記述が役に立つ。
なお、C#では代入も式である。MSDNを見てもらうと分かるが、「代入演算子」は「」に含まれている。そのため、setter内でメンバ変数に代入するのもラムダ式で書ける。

インデクサー

 インデクサーも、C# 6.0では読み取り専用のものをラムダ式で記述できる(次のコード)。

public class Group
{
  // Personオブジェクトを保持する、キー付きのコレクション
  private SortedList<string, Person> _persons 
    = new SortedList<string, Person>();

  // Personオブジェクトを追加するメソッド:ラムダ式で記述
  public void Add(string id, Person p) => _persons.Add(id, p);

  // 読み取り専用のインデクサー:ラムダ式で記述
  public Person this[string id] => _persons[id];
}

// 呼び出し例
var g = new Group();
g.Add("001", new Person { FirstName = "Yasuhiko", LastName = "Yamamoto" });
g.Add("002", new Person { FirstName = "Shinji", LastName = "Kawasaki" });
Console.WriteLine($"{g["002"].FullName}");
// ⇒出力: Shinji Kawasaki

ラムダ式を使った読み取り専用インデクサーの記述例
ここではラムダ式を使った記述のみを示す。Personクラスは、プロパティの説明のコードに登場しているものだ。Personクラスのインスタンスを作っているところの書き方は、「.NET TIPS:構文:インスタンス化と同時にプロパティを設定するには?[C#/VB]」を参照。

 C# 7.0では、通常のインデクサー(読み取りと書き込みの両方を備えたもの)もラムダ式で記述できる(次のコード)。

// 読み書きするインデクサー:ラムダ式で記述(C# 7.0)
public Person this[string id]
{
  get => _persons[id];
  set => _persons[id] = value;
}

ラムダ式を使った通常のインデクサーの記述例(C# 7.0)
C# 7.0からは、プロパティと同様にインデクサーのgetter/setterもラムダ式で書けるようになった。

コンストラクター/デストラクター/イベント(C# 7.0)

 以上の他に、C# 7.0からはコンストラクター/デストラクター/イベント(add/remove)もラムダ式での記述が可能になっている。

まとめ

 C# 6.0では、メソッドの内容がreturn文だけなら、ラムダ式を使って簡潔に記述できる。読み取り専用のプロパティとインデクサーも同様だ。

 さらにC# 7.0からは、プロパティのgetter/setter、インデクサーのgetter/setter、コンストラクター/デストラクター/イベント(add/remove)もラムダ式で書けるようになった。

利用可能バージョン:Visual Studio 2015(C# 6.0)以降
利用可能バージョン:Visual Studio 2017(C# 7.0)以降
カテゴリ:C# 処理対象:言語構文
関連TIPS:日付や時刻を文字列に変換するには?
関連TIPS:手軽にプロパティを実装するには?[C#、VS 2008、3.5]
関連TIPS:構文:インスタンス化と同時にプロパティを設定するには?[C#/VB]
関連TIPS:foreachループで現在の繰り返し回数を使うには?[C#/VB]


■更新履歴
【2017/07/05】Visual Studio 2017(C# 7.0)の新機能を使う方法を追加しました。
【2016/06/01】初版公開。


「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。