2009-10-30 4 views
3

J'ai une méthode Foo4 qui accepte un paramètre de type Func <>. Si je passe un paramètre de type anonyme, je n'obtiens aucune erreur. Mais si je crée et transmets un objet du type 'delegate' qui fait référence à une méthode avec une signature correcte, j'obtiens une erreur de compilation. Je ne suis pas capable de comprendre pourquoi je reçois une erreur dans ce cas.Passage de l'objet Delegate à la méthode avec le paramètre Func <>

class Learn6 
    { 
     delegate string Mydelegate(int a); 
     public void Start() 
     { 
      Mydelegate objMydelegate = new Mydelegate(Foo1); 

      //No Error 
      Foo4(delegate(int s) { return s.ToString(); }); 

      //This line gives compiler error. 
      Foo4(objMydelegate); 

     } 

     public string Foo1(int a) { return a.ToString();} 



     public void Foo4(Func<int, string> F) { Console.WriteLine(F(42)); } 
    } 
+0

Très bonne question, une autre façon de faire est Foo4 (s => s.ToString()); –

Répondre

8

Il fonctionne si vous passez une référence à la méthode directement:

Foo4(Foo1); 

Ceci est parce que les délégués réels avec la même forme ne sont pas intrinsèquement considérées comme compatibles. Si les contrats sont implicites, le compilateur déduit le contrat et les associe. Si elles sont explicites (par exemple, les types déclarés), aucune inférence n'est effectuée - ce sont simplement des types différents.

Il est semblable à:

public class Foo 
{ 
    public string Property {get;set;} 
} 

public class Bar 
{ 
    public string Property {get;set;} 
} 

Nous pouvons voir les deux classes ont la même signature et sont « compatibles », mais le compilateur les considère comme deux types différents, et rien de plus.

+0

Merci. J'ai appris maintenant qu'il est dû à des différences de type, mais que se passe-t-il lorsqu'une méthode anonyme est transmise à Foo4 comme dans le code original? – pradeeptp

+0

@pradeeptp car la méthode anonyme n'a pas de type, le type est inféré. –

+0

En effet, et personnellement je pense que c'est dommage qu'ils l'aient fait comme ça. Bien sûr, il peut y avoir des avantages pour les paramètres de nommage et une surcharge de _maybe_ sur des délégués différents avec la même "forme", mais quand même. Je suppose que la raison principale était le manque de support des génériques en C# 1, rendant impossible l'utilisation d'Action et de Func comme ils sont utilisés maintenant. – SoftMemes

4

Parce que Func<int, string> et MyDelegate sont différents déclarés types. Ils se trouvent être compatibles avec le même ensemble de méthodes; mais il n'y a pas de conversion implicite entre eux.

+0

Compris ce que vous avez dit, mais que se passe-t-il lorsque je passe delegate (int s) {return s.ToString(); } à Foo4 ?. Est-il implicitement converti en Func <>? – pradeeptp

+1

Essentiellement, oui. Le compilateur reconnaît que la méthode anonyme est un Func valide , et le convertit silencieusement en une déclaration 'string _Anon_Method_ (int s) {...}' et 'new Func (_Anon_Method_)'. Mais lorsque vous passez explicitement un MyDelegate où un Func est attendu, vous annulez cette conversion implicite et obtenez l'erreur du compilateur. – itowlson

0
 //This line gives compiler error. 
     Foo4(objMydelegate); 

     //This works ok. 
     Foo4(objMydelegate.Invoke); 
+0

Je ne savais pas qu'il pourrait être appelé comme ça. Un autre apprentissage. Merci! :) – pradeeptp

0

dépend du scénario, mais dans le cas général, il n'y a aucune raison de garder autour du type Mydelegate, il suffit d'utiliser Func < int, string > partout :)

Questions connexes