この記事ではC#においてMethod()()()のように()をつなげて引数を渡す方法を解説します。
私はvisual studio 2015で試しました。
呼び出しの具体例
static void Main(string[] args)
{
string result = MyStringJoin("aaa")("bbb")("ccc");
Console.WriteLine(result);
// 出力結果
//aaabbbccc
}
タイトルだけでは何の話をしているかさっぱりわからないと思うのですが、C#ではこのような変則的な書き方でもコンパイルエラーを出さずに実行できます。JAVAやC++ではあまり見ない形だと思います。
今回はこのメソッドの作成方法を解説したいと思います。
メソッドの作成方法
順を追って説明していきます。
呼び出し元で()が1つのとき
static void Main(string[] args)
{
string result = MyStringJoin1("aaa");
Console.WriteLine(result);
// 出力結果
//aaa
}
/// <summary>
/// 文字列1を受け取って文字列1を返す
/// </summary>
static string MyStringJoin1(string str1)
{
return str1;
}
見たとおり、文字列を一つ受け取ってそのまま返すメソッドです。これを増築していきたいと思います。
呼び出し元で()が2つのとき
static void Main(string[] args)
{
string result = MyStringJoin2("aaa")("bbb");
Console.WriteLine(result);
// 出力結果
//aaabbb
}
/// <summary>
/// 文字列1を受け取って
/// 文字列2を受け取って、文字列1と文字列2を結合するメソッドを返す
/// </summary>
static Func<string, string> MyStringJoin2(string str1)
{
return str2 => str1 + str2;
}
ここで重要なのはMyStringJoin2の戻り値の型である Func<string, string> です。Func<string, string>は、「string型を受け取ってstring型を返すメソッド」という意味です。詳しくは「定義済みデリゲート Func」でググッてください。これを戻り値とすることで、呼び出し元で入れ子のようにメソッドから別のメソッドを呼びだされ、上記のような呼び出し方ができるようになります。
return str2 => str1 + str2;の行ですが、ここは戻り値の型に合うように好きなメソッド定義を書きましょう。私はラムダ式を使用してメソッドを定義しました。他にはメソッド名を書いたり、匿名メソッドを書いたりできます。
呼び出し元で()が3つのとき
static void Main(string[] args)
{
string result = MyStringJoin3("aaa")("bbb")("ccc");
Console.WriteLine(result);
// 出力結果
//aaabbbccc
}
/// <summary>
/// 文字列1を受け取って
/// 文字列2を受け取って
/// 文字列3を受け取って、文字列1と文字列2と文字列3を結合するメソッドを返す
/// </summary>
static Func<string, Func<string, string>> MyStringJoin3(string str1)
{
return str2 => str3 => str1 + str2 + str3;
}
()が3つになるようにMyStringJoin2を増築するとこうなります。戻り値のFunc<string, Func<string, string>>ですが、日本語にすると「string型を受け取って、string型を受け取ってstring型を返すメソッドを返す、メソッドを返す」と読むと思います。
まとめ
Method()()()のような変則的な使い方ができるメソッドが書けるようになりましたが、使い所はあまりないと思います。
IT企業の入社試験で受験者に対して「これどうやって書くと思う?」みたいな嫌がらせに使えるのではないでしょうか。