Erreur «impossible d’implémenter le membre d’interface» lorsque l’interface et le béton sont dans des projets différents

Cela comstack:

public interface IMyInterface { event Action OnSomeEvent; } class MyInterface : IMyInterface { public event Action OnSomeEvent; } 

Mais quand je sépare l’interface et l’implémentation à différents projets, j’ai:

L’accesseur ‘TestProject2.MyInterface.OnSomeEvent.remove’ ne peut pas implémenter le membre d’interface ‘InterfaceNamespace.IMyInterface.remove_OnSomeEvent (System.Action)’ pour le type ‘TestProject2.MyInterface’. Utilisez une implémentation d’interface explicite.

Cela se produit uniquement avec un paramètre dynamic …

Bonne prise. Cela ressemble à un bogue dans le compilateur C # – je cinglerai Eric Lippert pour voir ce qu’il pense. ( dynamic peut être un peu truc; il peut bien y avoir une raison parfaitement bonne mais non évidente pour cette erreur.)

EDIT: Le code ci-dessous ne semble pas fonctionner après tout. J’aurais pu jurer que je travaillais ce matin … Je suis très confus quant à ce qui se passe. Selon les commentaires de Simon, le code échoue avec un message indiquant qu’il n’est pas pris en charge par le langage.

Notez que si vous utilisez une implémentation d’interface explicite, il semble bien comstackr:

 // Doesn't actually comstack - see edit above class MyInterface : IMyInterface { private Action foo; event Action IMyInterface.OnSomeEvent { // TODO (potentially): thread safety add { foo += value; } remove { foo -= value; } } } 

EDIT: Le rest de cette réponse tient toujours …

Notez que vous ne pouvez pas spécifier un événement de type champ en tant qu’événement explicitement implémenté, c’est-à-dire que cela ne fonctionne pas:

 event Action IMyInterface.OnSomeEvent; 

Il donne le message d’erreur suivant:

Test.cs (15,39): erreur CS0071: une implémentation d’interface explicite d’un événement doit utiliser la syntaxe de l’accesseur d’événement

Et si vous essayez simplement de passer à la syntaxe de l’access aux événements, vous obtenez la même erreur que le code d’origine.

Notez que la modification de l’événement en propriété fonctionne bien avec une implémentation de propriété implémentée automatiquement.

Merci d’avoir posté cette question, et merci à Jon de l’avoir envoyée. Je l’ai mis dans la queue d’investigation d’un de nos testeurs spécialisés en “dynamic”. Nous verrons si nous pouvons comprendre ce qui se passe ici. Ça sent certainement un bug.

À l’avenir, envisagez de publier ce genre de choses sur connect.microsoft.com; Cela le rend encore plus rapide aux testeurs et nous fournit un meilleur mécanisme pour obtenir plus d’informations sur le problème.

Cette réponse consiste à développer mes reflections sur ce problème intéressant. Pas une vraie réponse, mais une consortingbution à l’ensemble de la discussion qui est trop petite pour un commentaire normal .

J’ai vérifié quelques choses, cette interface:

 namespace DifferentAssemblyNamespace { public interface IBar { event Action OnSomeEvent; } } 

et sa mise en œuvre:

 // implicit interface implementation // generates comstack error "Explicit interface implementation" public class Foo1 : IBar { private Action foo; public event Action OnSomeEvent { add { foo += value; } remove { foo -= value; } } } // implicit interface implementation // generates comstack error "Not supported by the language" public class Foo2 : IBar { private Action foo; event Action IBar.OnSomeEvent { add { foo += value; } remove { foo -= value; } } } 

ne fonctionnera jamais , semble qu’une règle exclut l’autre règle nécessaire.

mais .. si nous appelons des génériques pour obtenir de l’aide, utilisez un paramètre Type au lieu d’utiliser directement la dynamic comme:

 namespace DifferentAssemblyNamespace { public interface IGenericBar { event Action OnSomeEvent; } } 

et sa mise en œuvre.

 // implicit interface implementation public class Foo3 : IGenericBar { private Action foo; event Action IGenericBar.OnSomeEvent { add { foo += value; } remove { foo -= value; } } } 

pour une raison quelconque, nous pouvons construire (comme il se doit) et exécuter:

 /** does build **/ IGenericBar f = new Foo3(); f.OnSomeEvent += new Action(f_OnSomeEvent); 

semble que le paramètre Type fait quelque chose de plus que le compilateur est heureux avec.

Je ne suis pas sûr de ce qui se passe, alors j’aimerais savoir aussi.

hypothèse, hautement hypothétique (peut-être de la merde)

mais actuellement je mets mes deux centimes sur la comparaison des types, il faut faire via les adders / supprimer des accesseurs dans la liste chaînée qui contient la cible / les méthodes de l’événement.

Je parie que le compilateur tombe dans le problème qu’il ne peut pas garantir la dynamic de l’assemblage externe, donc ne peut pas déterminer si un élément est déjà dans la liste ou non, ce qui est nécessaire pour les append ou les supprimer.

Nous soaps tous que ce n’est qu’une partie d’un object atsortingbué, mais il semble quand même que cela nécessite une étape supplémentaire où un type fort est garanti, et c’est ce que T fait, au moment de la compilation.

/ hypothèse, hautement hypothétique (peut-être de la merde)