当界面和具体在不同的项目中时,“不能实现接口成员”错误
这编译:
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在编译时所做的。
/假设,高度假设(也许是废话)