Impossible d’affecter à déléguer une méthode anonyme avec un type de paramètre moins spécifique

Je suis en mesure d’affecter une méthode M pour déléguer l’object d avec un type de paramètre moins spécifique, mais lorsque je souhaite affecter une méthode anonyme avec la même signature que la méthode M à d , un message d’erreur s’affiche.

Pourquoi donc?

 class derivedEventArgs : EventArgs { } delegate void newDelegate(object o, derivedEventArgs e); static void Main(ssortingng[] args) { newDelegate d = M; // ok d = (object o, EventArgs e) => { }; // error } public static void M(object o, EventArgs e) { } 

Jared a bien sûr raison de dire que c’est par sa conception.

La raison de cette conception est que, dans le cas d’une conversion de méthode contravariant, vous pouvez avoir une méthode que vous n’avez pas écrite et l’assigner à une variable de délégation que vous n’avez pas écrite non plus. Vous ne contrôlez pas les types. Nous allons donc un peu avec aisance et laissons les parameters concorder de manière contravariante et les types de retour concordent de manière covariante.

Dans la conversion lambda-à-délégué, vous contrôlez l’élément affecté. Rien ne vous empêche de faire une correspondance exacte dans les types de parameters et nous vous demandons donc de le faire. Pas de fogging autorisé ici.

Ceci est couvert dans la section 6.5 de la spécification du langage C #. Si vous tapez explicitement les parameters d’une fonction anonyme, ils doivent correspondre à la fois au type et aux modificateurs pour être des signatures compatibles.

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

Si F a une liste de parameters explicitement typée, chaque paramètre de D a le même type et les mêmes modificateurs que le paramètre correspondant de F.

Pendant que vous avez votre réponse, je fournirai une solution de contournement si cela est nécessaire . Disons que tout ce que vous avez est un délégué de signature (object, EventArgs) auquel cas vous voulez le convertir en 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 la fonctionnalité (contre) variance des delegates génériques, vous pouvez le faire avec un type de délégué:

 delegate void NewDelegate(object o, T e) where T : EventArgs; //then NewDelegate p = (object o, EventArgs e) => { }; //comes from somewhere NewDelegate d = p; //straightforward assignable - contravariance