[C#][ラムダ式][式木] Expression として扱えるラムダ式と扱えないラムダ式

Expression

前回、「匿名メソッドとラムダ式の違い」と云う記事で、匿名メソッドとラムダ式の意味の違いについて考えた。

それについて、少し補足しておきたい。

「ラムダ式を Expression として扱っている場合は、匿名メソッドは代わりにはならない」と述べたが、ラムダ式であれば何でも Expression として扱える訳ではないのだ。

■ Expression として扱えるラムダ式

ラムダ式として足し算を行うだけの (x, y) => x + y と云うシンプルなものを用意し、これを Expression で受けてみる。

using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Func<int, int, int>> expression = (x, y) => x + y;
}
}

これは特に問題ない。

■ Expression として扱えないラムダ式

ラムダ式の => より右の部分には式だけでなくステートメントのブロックも置くことができる。

このラムダ式の => より右の部分を、式ではなく、ステートメントのブロックに変えてみよう。
例えば、(x, y) => { return x + y; } とし、これを Expression で受けてみる。どうなるだろうか?

using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Func<int, int, int>> expression = (x, y) => { return x + y; };
}
}

すると今度は、「ステートメント本体を含むラムダ式は、式のツリーに変換できません」というコンパイル エラーになる。

「ステートメント本体を含むラムダ式は、式のツリーに変換できません」というコンパイル エラー

つまり、ラムダ式の => の右の部分が式である場合は Expression として扱えるが、ステートメントのブロックである場合は Expression として扱えないのだ。

■ 考察

「式でないものは式として扱えない」と云う、云わば当たり前の結果だ。

ところで、F# や Scala、Haskell などの関数型プログラミングをより得意とする言語では、if 等多くのものが式として扱える。

それらと比較すると、C# ではまだまだ式として書ける範囲は少ない。
例えば、if は文だ (勿論 C# でも三項演算子で書けるものは式で表現できる)。
だが、C# でもっと多くのものが、F# や Scala、Haskell などの言語のように文でなく式で表せるようになれば、益益 Expression で扱える範囲が増える、と云うことになるだろう。

■ 今回のまとめ

今回は、前回の記事の補足を軽く行った。

今後、ラムダ式を Expression として利用する例を何回かに分けて、紹介していく予定だ。

次回は、先ず Expression そのものへの理解を深めるために Expression の構造を調べてみたいと思う。