銀の弾丸

プログラミングに関して、いろいろ書き残していければと思っております。

C#のラムダ式はAction・Funcと一緒に理解を深めるとヨロシイようで

f:id:takamints:20160922160154p:plain
photo credit: Imperial Shuttle via photopin (license)

年に一度のパートタイム・シーシャーパー(C#erと書くらしいですね)ですが、今年は少し期間が長く、去年よりは深い仲になれそな予感がしています♪ とはいえパートタイム・シーシャーパー(もういい)なので、最新の動向を追いかけるのには四苦八苦。 てことで、今まで中途半端にしか理解していなかった ラムダ式について、現場で実際に使って理解したことを書いておきます。

ちなみに現場では、MVVM警察に怯えております。 「おいそこ!なんでクリックイベント拾ってるんだ!今すぐコマンド使いなさい!」みたいなビクビクもん。 いくつになってもお勉強です(泣

目次

※ タイトルにある ActionとFunc については以下のページで詳しく書いていますので参照してください。

takamints.hatenablog.jp

C#ラムダ式

C#逆引きレシピ
C#逆引きレシピ
posted with amazlet at 16.09.22
arton
翔泳社
売り上げランキング: 97,981

ラムダ式の記法的には、以下のような感じ。引数がひとつなら丸かっこは不要とか、波かっこの中身が単一の文なら(複文でないなら)波かっこは要らないとか、いろいろあるんだけど、基本はこちらでOKです。

(name,age) => {
    Console.WriteLine(
        string.Format(
            "{0} is {1} years old",
            name, age));
};

型とか指定されていないし、戻り値ってありなの?無しなの?どうでもいいの?てな具合に、全く情緒が安定しない代物ですが・・・

ラムダ式は無名関数ではありません

JavaScriptの即時関数的にラムダ式を直接呼び出そうとしてエラーになって「何がダメなの?」と混乱しました。 結構JavaScriptに慣れ親しんでいるので「C#ラムダ式ってJavaScriptの無名関数と一緒でしょ?関数オブジェクトそのものでしょ?」的な思い込みがあったんですね。

でもそれ間違いでした。 C#ラムダ式は無名関数ではありえないのです。つまり、・・・

ラムダ式というランタイムオブジェクトは無い

結局、ラムダ式を問題なく自由に使えるようになったのは、ActionクラスとFuncクラスを理解して、一緒に使うものだと認識してからでした。

それまでは、ラムダ式単体で見て「型が明示されていないのに、どうコンパイルされて実行されているのだ?」と不審に思っていました。 しかし、その、引数の数や型、戻り値の型など、欠落している情報は一緒に使われている ActionFunc、またはデリゲートで明示されているってことですね。

ラムダ式はそれらのオブジェクトを生成するために使われるんだけど、ランタイムに何らかのオブジェクトとして存在しているわけではないということです。

単なる記法、シンタックス・シュガーだよ

つまり「ラムダ式は、デリゲートやActionやFuncを記述するためのシンタックス・シュガーであって、それ自体はオブジェクトでもなんでもなく、単なる記法」というわけです。

その証拠に、JavaScriptの即時関数みたいなのは、C#ラムダ式だけでは実装不可

//JavaScriptの即時関数呼び出し
var a = 1;
(function(b) {
    a += b;
}(2));
console.log("a:", a);// "a: 3"

以下のように、一旦Actionインスタンスを作ってからでないと実行できない。Actionで第一引数がintであることを明示していますね。(敢えて似せて書いています。丸かっことかね)

int a = 1;
(new Action<int>(b => {
    a += b;
})(2));
Console.WriteLine(string.Format("a: {0}", a));

JavaScriptでの無名関数は関数オブジェクトだけど、C#ラムダ式に直接対応するオブジェクトはないってこと。 ちなみにJavaラムダ式は無名クラスのインスタンスだということです。

余談:シンタックス・シュガーの日本語訳

ところでこの度、シンタックス・シュガーが「糖衣構文」と訳されると知って軽くショックを受けています。 その昔、Perlラクダ本では「構文糖」と書かれていました(歳がバレる)。 これって、21世紀の現代的には「なにそれおじさん」なのでしょうか?震撼してます。