C#ラムダ式 基礎文法最速マスター

デジタルアドバンテージ 一色 政彦
2010/03/09

「★チートシート」はこちら

0. まえがき

 本稿では、小さいテーマではあるが、まだまだ慣れ親しんでいない開発者が少なくないと考えられる「ラムダ式(C#)」についての基礎文法を簡潔にまとめる。「ラムダ式、どう書くんだっけ?」という場合のリファレンスとして活用していただけるとうれしい。また、ラムダ式を敬遠しているという方は、まず本稿が学び始める取っ掛かりになるかもしれない(もちろん本稿の説明は充実しておらず、すべてを学べるわけではないので、じっくり学ぶには「連載:C# 3.0入門 第1回 ラムダ式」を参照してほしい)。

【コラム】「○○言語 基礎文法最速マスター」とは?

 今年(2010年)に入ってインターネット上では、プログラミング言語の基本文法を簡潔にまとめた「○○言語 基礎文法最速マスター」(以降、最速マスター・シリーズ)というブログ記事が多数投稿されている。参考までに、そのいくつかを示そう(そのほかについては、こちらを参照されたい)。

 これらの最速マスター・シリーズでは、基本的に短い説明とコード(+短いコメント)という構成になっており、プログラミング言語の基礎文法全体が一覧しやすいので、学び始めるきっかけとなるだけでなく、簡易リファレンスとしても活用できる。筆者の感想では、近年、英語圏で流行しているCheat Sheet(=あんちょこ、虎の巻、早見表)に通ずるものがある。ちなみに、筆者自身も最速マスター・シリーズやCheat Sheetのファンである。

1. ラムダ式(C#)の概要

ラムダ式とは何か?

 C#言語のラムダ式(lambda expressions)とは、デリゲート(delegate)や、メソッド・ベースのLINQ文の(例えば)WhereメソッドやSelectメソッドなどの引数をシンプルに記述するために、C# 3.0(=Visual C# 2008)以降で導入された言語仕様である。

 なおデリゲートとは、メソッドを参照するための型を定義して、その型のインスタンスをメソッドとして呼び出すための機能であり、主にイベント・ハンドラやコールバック・メソッドとして活用されている。

 メソッド・ベースのLINQ文の(例えば)Whereメソッドには下記の2種類があり、ラムダ式はそれぞれ右記の型に暗黙的に変換される(詳しくは「特集:C#プログラマーのためのLINQ超入門」を参照)。

ラムダ式で記述したイベント・ハンドラの例

 次のコードは、Windowsフォーム・アプリケーションにおけるボタンのClickイベント・ハンドラのデリゲートを通常文法で記述した例と、それを匿名メソッドで記述した例、さらにそれをラムダ式にした例である。

public Form1()
{
  ……省略……
  button1.Click += button1_Click;
}

void button1_Click(object sender, EventArgs e)
{
  MessageBox.Show("デリゲート!");
}
通常文法で記述したイベント・ハンドラのサンプル・コード
「button1.Click += 」には、EventHandler型のデリゲート・インスタンスを指定する必要がある。つまり、このコード例でいえば「new EventHandler(button1_Click)」と記述する必要があるが、「new EventHandler( )」という記述は.NET Framework 2.0以降では省略可能となっている(つまり、メソッド名のみを設定すればよい)。このコード例でも省略されている。

↓ 匿名メソッド

public Form1()
{
  ……省略……
  button1.Click += delegate(object sender, EventArgs e)
  {
    MessageBox.Show("匿名メソッド!");
  };
}
匿名メソッドで記述したイベント・ハンドラのサンプル・コード

↓ ラムダ式

public Form1()
{
  ……省略……
  button1.Click += (sender, e) => MessageBox.Show("ラムダ!");
}
ラムダ式で記述したイベント・ハンドラのサンプル・コード

ラムダ式で記述したLINQ文の例

 次のコードは、コンソール・アプリケーションにおけるメソッド・ベースのLINQ文のデリゲートを通常文法で記述した例と、それを匿名メソッドで記述した例、さらにそれをラムダ式で記述した例である。

static void Main()
{
  var dataSource = Enumerable.Range(1, 100);

  var query = dataSource.Where(WhereMethod);

  foreach (var num in query) { Console.WriteLine(num); }
}

static bool WhereMethod(int i)
{
  return i % 13 == 0;
}
通常文法で記述したLINQ文のサンプル・コード
Whereメソッドには、Func<TSource, bool>デリゲート型の引数を指定する(Whereメソッドには、異なる引数を受け取るオーバーロード・メソッドが存在する)。

↓ 匿名メソッド

static void Main()
{
  var dataSource = Enumerable.Range(1, 100);

  var query = dataSource.Where(delegate(int i)
  {
      return i % 13 == 0;
  });

  foreach (var num in query) { Console.WriteLine(num); }           
}
匿名メソッドで記述したLINQ文のサンプル・コード

↓ ラムダ式

static void Main()
{
  var dataSource = Enumerable.Range(1, 100);

  var query = dataSource.Where(i => i % 13 == 0);

  foreach (var num in query) { Console.WriteLine(num); }
}
ラムダ式で記述したLINQ文のサンプル・コード

2. ラムダ式(C#)の基礎文法

ラムダ式の基本構文

左辺 => 右辺
ラムダ式の基本構文

ラムダ式構文の左辺

 左辺には、デリゲートとして呼び出されるメソッドのパラメータが入る(「入力パラメータ」と呼ばれる)。基本的にパラメータは ( ) で囲む必要があるが、パラメータが1つのみの場合は、( ) は省略可能だ。パラメータが複数の場合、各パラメータは「,」で区切る。

() => 右辺                 // パラメータがない場合
param => 右辺              // パラメータが1つの場合
(param1, param2) => 右辺   // パラメータが2つ以上の場合
ラムダ式の基本構文

 パラメータでは通常、型はコンパイラによって自動的に推論されるので、上記のように型指定を行わない。しかし必要があれば、型指定を行うことも可能だ。

(int param) => 右辺        // パラメータの型指定
パラメータにint型を指定した例(特殊なケース)

左辺:パラメータの例

 冒頭のイベント・ハンドラとLINQ文のサンプル・コード(の一部)を用いて、実際にパラメータがどのように記述されるかを確認する。

button1.Click += (sender, e) => <右辺>;
パラメータの確認:イベント・ハンドラのサンプル・コード

 この例では、senderとeがパラメータである。もともとのデリゲート型は次のとおりだ。

delegate void EventHandler(object sender, System.EventArgs e)

 また、次のLINQ文の例では、「i」がパラメータである。

var query = dataSource.Where(i => <右辺>);
パラメータの確認:LINQ文のサンプル・コード

 もともとのデリゲート型は次のとおり。上記の「i」と下記の「arg」が一致している。

delegate TResult Func<T, TResult>(T arg)

ラムダ式構文の右辺

 右辺には、式か文を指定する。

左辺 => 式
左辺 => { 文; 文; 文; }

右辺:「式」形式のラムダ

 式(expression)とは、プログラミング・コードでいうところの「式」のことで、演算子を使った「i % 13 == 0」も式であれば、メソッド呼び出しの「MessageBox.Show("メソッド!")」も式である。式の最後には、セミコロン(;)を付けないのがポイント。

 冒頭のイベント・ハンドラとLINQ文のサンプル・コードにおけるラムダ式は、「式」形式で記述されている。

button1.Click += (sender, e) => MessageBox.Show("式!");
「式」形式で記述したラムダ式:イベント・ハンドラのサンプル・コード

var query = dataSource.Where(i => i % 13 == 0);
「式」形式で記述したラムダ式:LINQ文のサンプル・コード

右辺:「文」形式のラムダ

 文(statement)とは、式の最後にセミコロン(;)を付けたもの。文形式のラムダでは、その文は必ず { } (=ブロック)で囲む。戻り値が必要な場合には、returnキーワードで返却する値を明記する。

 冒頭のイベント・ハンドラとLINQ文のサンプル・コードにおけるラムダ式を、「文」形式で記述すると次のようになる。上の式形式とよく見比べてほしい。

button1.Click += (sender, e) => { MessageBox.Show("文!"); };
「文」形式で記述したラムダ式:イベント・ハンドラのサンプル・コード

var query = dataSource.Where(i => { return i % 13 == 0; });
「文」形式で記述したラムダ式:LINQ文のサンプル・コード

 なお、次のコード例のように、文はブロック内に複数記述できる。

button1.Click += (sender, e) =>
{
  int count = 3;
  string msg = String.Format("{0}つの文です。", count);
  MessageBox.Show(msg);
};
複数の文を記述したラムダ式:イベント・ハンドラのサンプル・コード

戻り値について

 デリゲートによっては戻り値を必要としない(=戻り値がvoid型の)場合もある。上記のイベント・ハンドラのサンプル・コードは、戻り値を返さない例である。逆に、上記のLINQ文のサンプル・コードは、戻り値を返す例である。

 前述した「式形式のラムダ」を見ると分かるように、式形式のラムダでは戻り値を明示しない、つまりreturnキーワードは記述しないので注意してほしい。一方、文形式のラムダは戻り値が必要な場合は、returnキーワードで戻り値を明記する必要がある。

ラムダ式のスコープ外部にある変数やメソッドの利用

 ラムダ式では、そのスコープの外側にある変数やメソッドを利用できる。

string outerVariable = "外部変数";

button1.Click += (sender, e) =>
{
  string msg = outerVariable;
  MessageBox.Show(msg);
};
ラムダ式のスコープ外部にある変数の利用

public Form1()
{
  ……省略……
  button1.Click += (sender, e) =>
  {
    string msg = OuterMethod();
    MessageBox.Show(msg);
  };
}

public string OuterMethod()
{
  return "外部メソッド";
}
ラムダ式のスコープ外部にあるメソッドの利用

「=>演算子」の読み方

 「=>」は「goes to」(ゴーズ・トゥ)と読む。意訳すると、「左辺のパラメータを入力して、右辺の式/文を実行する。戻り値が必要な場合は、その戻り値を返す」という意味になる。End of Article

筆者による.NET/Azure関連の情報共有について

はてなブックマークやTwitterで、主に.NET/Windows Azure開発関連の情報共有を行っています。はてなブックマークでは、主に英語のブログへのリンク共有を行っています。Twitterでは、リンク共有に加え、簡単な投稿も行っています。どちらもフォローしたり、RSSフィードを購読したりできます。


インデックス・ページヘ  「.NET開発『虎の巻』」

@IT Special

- PR -

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
  • 第7回 Windowsアプリのデバッグ&リリース (2017/7/14)
     バグはどうやってつぶせばいいのか? 完成したアプリケーションはどうやってリリースすればいいのか? VS 2017入門の最終回
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

イベントカレンダー

PickUpイベント

- PR -

アクセスランキング

もっと見る

ホワイトペーパーTechTargetジャパン

注目のテーマ

Insider.NET 記事ランキング

本日 月間
ソリューションFLASH