2017-08-09 6 views
0

J'ai la méthode locale suivante.Pourquoi ma fonction générique d'ordre supérieur n'acceptera-t-elle pas un groupe de méthodes comme argument?

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

et moi avons une fonction d'ordre supérieur tel que défini ci-dessous

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); 

} 

Il divise la fonction originale en deux appels de fonction. La première fonction accepte les deux premiers arguments et la seconde l'argument final. Lorsque la deuxième fonction est appelée, la fonction d'origine est appelée avec tous les arguments.

Une utilisation simple

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

sortie après cfn2 est appelé devrait être

"0 1 3"  

mais le compilateur C# ne permettra pas à ce sujet.

Les arguments de type pour la méthode 'Curry.act2f3 (Action)' ne peuvent pas être déduits de l'utilisation. Essayez de spécifier explicitement les arguments de type .

Cependant, la commande ne fonctionne

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

mais ne permet pas vraiment car il va à l'encontre du but d'écrire cette bibliothèque en premier lieu. Le but étant un processus DRY de manipulation d'arguments de fonction.

Y at-il un truc subtil qui me manque pour que ça marche?

+2

L'inférence de type générique n'implémente pas l'analyse heuristique approfondie, elle arrête fréquemment une couche ou avant qu'elle ne puisse déduire les types impliqués, puis crache cette erreur. –

+0

Souvent, je passe les groupes de méthodes aux fonctions LINQ et il n'y a pas de problème. Quel est le problème spécifique ici qui empêche les groupes de méthodes d'être interchangeables avec lambdas? – bradgonesurfing

+0

Une partie du problème ici (je pense) est qu'il y a deux types d'inférence en jeu, que les délégués construisent autour de 'Test', et les types génériques dans la méthode. Si vous essayez ceci: Curry.act2f3 (nouvelle Action (Test)), alors il compile. –

Répondre

0

C'est l'incapacité malheureuse du compilateur C# d'inférer les paramètres de type de la fonction passée Test.

L'instruction Curry.act2f3((int i, int j, int k) => Test(i, j, k)); fonctionne parce que vous avez spécifié les types int dans la déclaration (int i, int j, int k).

Le var cfn = Curry.act2f3(Test); fonctionnera si vous spécifiez les types génériques comme ceci:

var cfn = Curry.act2f3<int, int, int>(Test);.