当界面和具体在不同的项目中时,“不能实现接口成员”错误

这编译:

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

但是当我把接口和实现分开到不同的项目时,我得到:

访问器'TestProject2.MyInterface.OnSomeEvent.remove'不能为types'TestProject2.MyInterface'实现接口成员'InterfaceNamespace.IMyInterface.remove_OnSomeEvent(System.Action)'。 使用明确的接口实现。

这只发生在一个dynamic参数…

接得好。 这看起来可能是C#编译器中的一个错误 – 我会通过Eric Lippert来看看他的想法。 ( dynamic可能有点棘手;可能有一个完美的但不明显的原因,这个错误。)

编辑: 下面的代码似乎工作毕竟。 今天早上我可以发誓我已经开始工作了……对于发生了什么,我感到非常困惑。 根据Simon的评论,代码失败,并显示消息说不支持该语言。

请注意,如果你使用显式的接口实现,它似乎编译得很好:

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

编辑:这个答案的其余部分仍然站在…

请注意,您不能将一个类似于事件的事件指定为一个显式实现的事件,也就是说这不起作用:

 event Action<dynamic> IMyInterface.OnSomeEvent; 

它给出了以下错误信息:

Test.cs(15,39):错误CS0071:事件的显式接口实现必须使用事件访问器语法

如果您只是尝试更改为事件访问器语法,则会得到与原始代码相同的错误。

请注意,将事件更改为属性可以很好地与自动实现的属性实现一起使用。

感谢张贴这个问题,并感谢乔恩发送我的方式。 我把这个放在我们的一个专门研究“dynamic”的testing人员的调查队列中。 我们会看看我们能不能弄清楚这里发生了什么。 它当然闻起来像一个错误。

将来,请考虑在connect.microsoft.com上发布这样的内容。 让testing人员更快,并为我们提供更好的机制来获取有关该问题的更多信息。

这个答案是对这个有趣的问题进行精心的思考。 不是一个真正的答案,而是对整个讨论的贡献, 对于一个正常的评论来说太小了

我检查了几个东西,这个接口:

 namespace DifferentAssemblyNamespace { public interface IBar { event Action<dynamic> OnSomeEvent; } } 

及其实施:

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

将永远不会工作 ,似乎有一条规则是排除其他必要的规则。

但是..如果我们称为generics帮助,并使用types参数,而不是直接使用dynamic ,如:

 namespace DifferentAssemblyNamespace { public interface IGenericBar<T> { event Action<T> OnSomeEvent; } } 

及其实施。

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

出于某种原因,我们可以build立(如它应该)并运行:

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

看起来types参数做了一些额外东西 ,编译器很满意。

我不确定发生了什么,所以我想知道。

假设,高度假设(也许是废话)

但是现在我把我的两分钱放在比较types的时候必须通过链表中的add / remove访问器来保存事件的目标/方法。

我敢打赌,编译器不能保证外部程序集中的dynamic是什么,因此不能确定一个元素是否已经在列表中,这是必须添加或删除的(因此显式的接口实现)

我们都知道这仅仅是一个归属对象的一部分,但它似乎仍然需要一个额外的步骤来保证一些强types,这就是T在编译时所做的。

/假设,高度假设(也许是废话)