2010-02-18 5 views
14

Je peux affecter une méthode M pour déléguer l'objet d avec un type de paramètre moins spécifique, mais lorsque je souhaite affecter une méthode anonyme avec la même signature comme méthode M à d, j'obtiens une erreur.Impossible d'affecter pour déléguer une méthode anonyme avec un type de paramètre moins spécifique

Pourquoi est-ce?

class derivedEventArgs : EventArgs { } 

delegate void newDelegate(object o, derivedEventArgs e); 

static void Main(string[] args) 
{ 
    newDelegate d = M; // ok 
       d = (object o, EventArgs e) => { }; // error 
} 

public static void M(object o, EventArgs e) { } 
+2

Vous avez certainement des conventions de nommage intéressantes qui s'y passent ... –

Répondre

15

Jared est bien sûr correct que cela soit voulu. La raison de cette conception est que dans le cas de conversion de méthode contravariant, vous pouvez avoir une méthode que vous n'avez pas écrite, et l'affecter à une variable de délégué que vous n'avez pas écrite non plus. Vous ne contrôlez pas les types. Donc, nous allons un peu facilement sur vous et laissons les paramètres correspondre de manière contravariante et les types de retour correspondent covariant.

Dans la conversion lambda-à-déléguée, contrôle l'objet affecté. Il n'y a rien vous arrêtant vous de faire une correspondance exacte dans les types de paramètres et par conséquent nous besoin de vous. Aucun fudging autorisé ici.

+0

Great answers.Thank vous deux pour m'aider – AspOnMyNet

16

Ceci est traité dans la section 6.5 de la spécification de langage C#. Si vous tapez explicitement les paramètres d'une fonction anonyme, ils doivent correspondre à la fois au type et aux modificateurs afin d'être des signatures compatibles.

Plus précisément, un type de délégué D est compatible avec une fonction anonyme F fournie

...

Si F a une liste de paramètres explicitement typé, chaque paramètre D a le même type et modificateurs comme le paramètre correspondant dans F.

+1

+ 1 réponse très rapide. –

2

Alors que vous avez votre réponse, je vais fournir une solution de contournement si cela est requis. Dites, tout ce que vous avez est un délégué de la signature (object, EventArgs) dans ce cas, vous voulez convertir à votre type newDelegate, vous pouvez faire:

SomeDelegate p = (object o, EventArgs e) => { }; //comes from somewhere 
NewDelegate d = (o, e) => p(o, e); //can rewrite like this 

alternativement avec les génériques et fonction de la variance (contre) des délégués génériques, vous pouvez le faire avec un type de délégué:

delegate void NewDelegate<in T>(object o, T e) where T : EventArgs; 

//then 
NewDelegate<EventArgs> p = (object o, EventArgs e) => { }; //comes from somewhere 
NewDelegate<DerivedEventArgs> d = p; //straightforward assignable - contravariance 
Questions connexes