読者です 読者をやめる 読者になる 読者になる

それ,名前のあるメソッドで書けないよ

.NET

Boost.Bind を C# で作りたい(2) - melt日記』より.

とりあえず全部の引数を束縛するのであれば簡単に作れるようだ。

delegate R Function<R>();
delegate R Function<R, T1>(T1 t1);
delegate R Function<R, T1, T2>(T1 t1, T2 t2);
// 以下略

Function<R> Bind<R>(Function<R> f)
{
    return delegate { return f(); };
}
Function<R> Bind<R, T1>(Function<R, T1> f, T1 t1)
{
    return delegate { return f(t1); };
}
Function<R> Bind<R, T1, T2>(Function<R, T1> f, T1 t1, T2 t2)
{
    return delegate { return f(t1, t2); };
}
// 以下略

でもこれだと、

int func(int n) { return 0; }

Function<int> f = Bind(func, 100);

と書くと

'Bind<R,T1>(Function<R,T1>, T1)' に対する型引数を使い方から推論することはできません。型引数を明示的に指定してください。

って出る。ダメポ。

Method group conversions と Generic Method の型推論の順序の兼ね合いで,これエラーになっちゃうんですな.C# 3.0 でも同じエラー.
でも C# 3.0 のラムダ式や C# 3.0 の Anonymous Delegate だと OK.不思議?*1

using System;
using System.Collections.Generic;

delegate R Function<R>();
delegate R Function<R, T1>(T1 t1);

static class Program
{
    static Function<R> Bind<R, T1>(Function<R, T1> f, T1 t1)
    {
        return delegate { return f(t1); };
    }

    static int func(int n) { return 0; }

    static void Main(string[] args)
    {
        // compile error (C# 2.0, C# 3.0) / OK (C# 4.0)
        Function<int> f1 = Bind(func, 100);

        // OK (C# 3.0, C# 4.0)
        Function<int> f2 = Bind(n => 0, 100);

        // compile error (C# 2.0) / OK (C# 3.0, C# 4.0)
        Function<int> f3 = Bind(delegate(int n) { return 0; }, 100);
    }
}

f3 の振る舞いはちょっと印象的.C# 2.0 だとエラーになるけど C# 3.0 だとエラーにならない.びっくり?

参考資料

追記

*1:理由は参考資料参照のこと