CodeZine に .NET3.5 の導入記事があったので読んでみたのだが、そりゃ違うだろってところがあったのでそれについて。
ラムダ式とは、ある処理を行い、単一の結果を返却する名前を持たないメソッドを定義する機能です。このメソッドはデリゲート型として利用することができ、定義したラムダ式を変数に代入しておくことも可能です。ラムダ式を利用した場合、戻り値の型を明示的に指定することはできませんが、処理内容から戻り値の型は自動的に型推論されます。
( とことん理解する .NET Framework3.5, WINGS プロジェクト りばてぃ / FUJIKO / ナオキ 著, 2008/03/07 )
違うところは以下の2点
- 名前を持たないメソッドを定義する機能
- 戻り値の型を明示的に指定することはできません
まず、C# においては「名前を持たないメソッドを定義する機能」という記述は正確ではない。正確には「名前を持たないメソッドも定義できる機能」ということになる。実際、リンク先の例ではメソッドに func という名前が付いている。
次に「戻り値の型を明示的に指定することはできない」というのも大ウソ。型推論に任せることもできるが、プログラマが戻り値を指定することもちゃんとできる。
名前を持たず、かつ戻り値の型も明示した場合の例は↓のようになる。
using System;
class SampleClass{
static int Main(){
System.Console.Write(
((Func< int, int, bool >)((i, j) => i == j))( 1, 3 )
);
return 0;
}
}
この例では Func< int, int, bool > の部分で引数と戻り値の型を指定している。続く((i, j) => i == j) と合わせることで引数 i, j は int 型であり、戻り値は bool 型であることがわかる。そして、定義した関数にすぐさま2つの引数を渡している。定義している関数は完全な無名なので、後でなにか識別子名を利用してこの関数を呼び出すということはできない。
まだ理解が怪しいのだが、実際には ((i, j) => i == j) を Func< int, int, bool > という型にキャストすることになるようだ。
さて、ラムダ式に渡されている引数を "hoge" と "piyo" にして再度コンパイルしてみてほしい。コンパイルエラーになるはずだ。わたしの環境では以下のエラーが表示された。
C:\dev>csc lambda_test.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.21022.8
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
lambda_test.cs(6,13): error CS1594: Delegate 'System.Func<int,int,bool>' has
some invalid arguments
lambda_test.cs(6,59): error CS1503: Argument '1': cannot convert from 'string'
to 'int'
lambda_test.cs(6,67): error CS1503: Argument '2': cannot convert from 'string'
to 'int'
見てのとおり型が一致しないというエラーだ。エラーメッセージを要約すると「第一引数と第二引数は int 型が指定されているが string 型が渡されてきた。これは無効な引数だぞ」というわけだ。
では次に Func< int, int, bool > を Func< int, int, int > に置き換えてコンパイルしてみてほしい。やはりコンパイルエラーになると思う。たとえばこんなエラーが表示される。
C:\dev>csc lambda_test.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.21022.8
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
lambda_test.cs(6,48): error CS0029: Cannot implicitly convert type 'bool' to
'int'
lambda_test.cs(6,48): error CS1662: Cannot convert lambda expression to delegate
type 'System.Func<int,int,int>' because some of the return types in the
block are not implicitly convertible to the delegate return type
こちらもやはり「型が一致しない」というエラーだ。それもちゃんと「戻り値の型が一致しない」という内容になっている。
というように完全にユーザ定義の識別子名を付けないメソッド定義も可能だし、戻り値とか引数の型を指定することも可能なのだ。