MISE À JOUR FINALE :
Le bogue a été corrigé dans C# 5. Toutes nos excuses pour le désagrément, et merci pour le rapport.
Analyse originale :
Je peux reproduire le problème avec le compilateur en ligne de commande. Cela ressemble certainement à un bug. C'est probablement ma faute ; désolé. (J'ai écrit tout le code de vérification de la conversion lambda-délégué).
Je suis dans un café en ce moment et je n'ai pas accès aux sources du compilateur d'ici. Je vais essayer de trouver un peu de temps pour reproduire ce problème dans la version de débogage demain et voir si je peux comprendre ce qui se passe. Si je ne trouve pas le temps, je serai absent du bureau jusqu'après Noël.
Votre observation selon laquelle l'introduction d'une variable de type Action fait disparaître le problème est extrêmement intéressante. Le compilateur maintient de nombreux caches à la fois pour des raisons de performance et pour l'analyse requise par la spécification du langage. Les lambdas et les variables locales, en particulier, ont une logique de mise en cache très complexe. Je serais prêt à parier jusqu'à un dollar qu'un cache est initialisé ou rempli de manière incorrecte ici, et que l'utilisation de la variable locale remplit la bonne valeur dans le cache.
Merci pour le rapport !
MISE À JOUR : je suis maintenant dans le bus et cela m'est venu à l'esprit ; je pense savoir exactement ce qui ne va pas. Le compilateur est perezoso en particulier lorsqu'il s'agit de types provenant de métadonnées. La raison en est qu'il peut y avoir des centaines de milliers de types dans les assemblages référencés et qu'il n'est pas nécessaire de charger des informations sur chacun d'entre eux. Vous allez probablement utiliser beaucoup moins de 1% d'entre eux, alors ne gaspillons pas beaucoup de temps et de mémoire à charger des choses que vous n'utiliserez jamais. En fait, la paresse est plus profonde que cela ; un type passe par plusieurs "étapes" avant de pouvoir être utilisé. D'abord son nom est connu, puis son type de base, puis si sa hiérarchie de type de base est bien fondée (acyclique, etc.), puis ses contraintes de paramètres de type, puis ses membres, puis si les membres sont bien fondés (que les surcharges surchargent quelque chose de la même signature, et ainsi de suite). leur membres connus", avant de vérifier la signature de l'invocation du délégué pour la compatibilité. Mais le code qui rend une variable locale probablement hace faire ça. Je pense que lors de la vérification de la conversion, le type Action peut même ne pas avoir de méthode invoke pour le compilateur.
Nous le saurons bientôt.
MISE À JOUR : Mes pouvoirs psychiques sont forts ce matin. Lorsque la résolution de surcharge tente de déterminer s'il existe une méthode "Invoke" du type délégué qui prend zéro argument, elle trouve zéro méthode d'invocation au choix . Nous devrions nous assurer que les métadonnées du type de délégué sont entièrement chargées avant de procéder à la résolution des surcharges. Il est étrange que cela soit passé inaperçu aussi longtemps ; cela se reproduit en C# 3.0. Bien sûr, il ne se reproduit pas en C# 2.0 simplement parce qu'il n'y avait pas de lambdas ; les méthodes anonymes en C# 2.0 exigent que vous indiquiez le type explicitement, ce qui crée un local, qui, nous le savons, charge les métadonnées. Mais j'imagine que la cause première du bogue - le fait que la résolution des surcharges ne force pas le chargement des métadonnées pour l'invocation - remonte au C# 1.0.
Quoi qu'il en soit, un bug fascinant, merci pour le rapport. Vous avez manifestement trouvé une solution de contournement. Je vais demander au service d'assurance qualité de suivre le problème à partir d'ici et nous essaierons de le corriger pour C# 5. Service Pack 1, qui est déjà en version bêta. .)