2017-08-09 4 views
0

私は以下のローカルメソッドを持っています。一般的な高次関数がメソッドグループを引数として受け入れないのはなぜですか?

void Test(int i, int j, int k) { 
    Console.WriteLine($"{i} {j} {k}"); 
} 

とそれが2つの関数呼び出しに本来の機能を分割

public static class Curry { 
    public static Func<T0, T1, Action<T2>> 
     act2f3<T0, T1, T2>(Action<T0, T1, T2> fn) => 
      (T0 t0, T1 t1) => (T2 t2) => fn(t0, t1, t2); 

} 

下に定義されるように、私は、より高次の機能を有します。最初の関数は最初の2つの引数を受け取り、2つ目は最後の引数を受け取ります。 2番目の関数が呼び出されると、元の関数がすべての引数で呼び出されます。

簡単な使い方はcfn2は、C#コンパイラがこれを許可しませんが

"0 1 3"  

あるべきと呼ばれた後

var cfn = Curry.act2f3(Test); 
var cfn2 = cfn(0,1); 
cfn2(3); 

出力されます。

メソッド 'Curry.act2f3(Action)'の型引数は、その使用法から推論できません。タイプ を明示的に指定してみてください。以下は、

Curry.act2f3((int i, int j, int k) => Test(i, j, k)); 

に動作しますが、それは最初の場所でこのライブラリを書くの目的に反して、本当に助けにはならない。しかし

その目的は、関数の引数を操作するプロセスです(DRY)。

これを行うには微妙なトリックがありますか?

+2

一般型推論は深いヒューリスティックを実装していないため、頻繁に1つのレイヤーを停止させたり、関連するタイプを推測してからそのエラーを吐き出すことができます。 –

+0

メソッドグループをLINQ関数に渡すことはよくあり、問題はありません。ラムダと交換可能な方法群を停止させる特定の問題は何ですか? – bradgonesurfing

+0

ここで問題になっているのは(私は)、 'Test'とそのメソッドのジェネリック型の周りに構築するために委譲される演繹には2つのタイプの推論があるということです。これを試してみると、 'Curry.act2f3(新しいアクション(テスト));'それがコンパイルされます。 –

答えて

0

C#コンパイラが、渡された関数の型パラメータを邪魔してしまうという不幸なことは、Testです。

タイプを(int i, int j, int k)と指定したため、Curry.act2f3((int i, int j, int k) => Test(i, j, k));ステートメントが機能します。

var cfn = Curry.act2f3<int, int, int>(Test);:あなたはこのような一般的なタイプを指定した場合

var cfn = Curry.act2f3(Test);は動作します。

関連する問題