C# &引用;无法实现接口成员“;接口和混凝土在不同项目中时出错
这包括:C# &引用;无法实现接口成员“;接口和混凝土在不同项目中时出错,c#,events,dynamic,C#,Events,Dynamic,这包括: public interface IMyInterface { event Action<dynamic> OnSomeEvent; } class MyInterface : IMyInterface { public event Action<dynamic> OnSomeEvent; } 公共接口IMyInterface { 对某些事件的事件操作; } 类MyInterface:IMyInterface { 针对某些事件的公共事件行动;
public interface IMyInterface
{
event Action<dynamic> OnSomeEvent;
}
class MyInterface : IMyInterface
{
public event Action<dynamic> OnSomeEvent;
}
公共接口IMyInterface
{
对某些事件的事件操作;
}
类MyInterface:IMyInterface
{
针对某些事件的公共事件行动;
}
但是,当我将接口和实现分离到不同的项目时,我得到:
存取器
'TestProject2.MyInterface.OnSomeEvent.remove'
无法实现接口成员
'InterfaceNamespace.IMyInterface.remove_OnSomeEvent(System.Action)'
对于类型“TestProject2.MyInterface”。
使用显式接口
实施
// 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; }
}
}
这仅在动态参数下发生…捕捉良好。这看起来可能是C#编译器中的一个bug——我会打电话给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; }
}
}
//实际上没有编译-请参见上面的编辑
类MyInterface:IMyInterface
{
私人行动基金;
事件操作IMyInterface.OnSomeEvent
{
//TODO(潜在):线程安全
添加{foo+=value;}
删除{foo-=value;}
}
}
编辑:这个答案的其余部分仍然有效 请注意,不能将类似字段的事件指定为显式实现的事件,即,这不起作用:
event Action<dynamic> IMyInterface.OnSomeEvent;
事件操作IMyInterface.OnSomeEvent;
它给出以下错误消息:
cs(15,39):错误CS0071:事件的显式接口实现必须使用事件访问器语法
如果您只是尝试更改事件访问器语法,则会得到与
原始代码
请注意,将事件更改为属性可以与自动实现的属性实现配合使用。感谢您发布此问题,也感谢Jon向我发送此问题。我已经把它放在我们的一位测试人员的调查队列中,他专门研究“动态”。我们看看能不能弄清楚这里发生了什么。它闻起来真像虫子
// 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; }
}
}
将来,考虑把这样的东西张贴到Calp.MyStftcom上;这让测试人员更快地了解它,并为我们提供了一个更好的机制来获取关于这个问题的更多信息。
这个答案是为了阐述我对这个有趣问题的想法。这不是一个真正的答案,而是对整个讨论的贡献,对于一个普通的评论来说,这个贡献太小了 我检查了一些东西,这个界面:namespace DifferentAssemblyNamespace
{
public interface IBar
{
event Action<dynamic> 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; }
}
}
//隐式接口实现
公共类Foo3:IGenericBar
{
私人行动基金;
事件操作IGenericBar.OnSomeEvent
{
添加{foo+=value;}
删除{foo-=value;}
}
}
出于某种原因,我们可以构建(它应该)并运行:
/**确实可以构建**/
IGenericBar f=新的Foo3();
f、 OnSomeEvent+=新操作(f_OnSomeEvent);
类型参数似乎做了一些编译器满意的额外工作
我不知道发生了什么,所以我也想知道
假设,高度假设(可能是废话)
但是现在我把我的两分钱放在
类型的比较必须是
通过中的“添加/删除访问者”创建
保存链接的链接列表
事件的目标/方法
我敢打赌
编译器在
它不能保证什么的问题
dynamic位于外部程序集中,因此无法确定元素是否已在列表中,这是添加或删除它们所必需的。(因此显式接口实现)
我们都知道这只是一个小问题
属性化对象,但它仍然看起来
它需要一个额外的步骤
强类型是有保证的,这就是
T在编译时所做的事情
/假设,高度假设性(可能是废话)我想知道编译器如何知道如何保护覆盖,然后在您分开编译项目时识别如何处理动态。是否有任何配置使显式接口实现工作?我收到一个
错误CS0682:“ConsoleApplication1.MyInterface.ClassLibrary1.IMyInterface.OnSomeEvent”无法实现“ClassLibrary1.IMyInterface.OnSomeEvent”,因为它不受试图编译的语言的支持。@Simon:您使用的是什么版本的C#编译器?动态是在C#4中引入的。@Caspar:对不起,我刚刚注意到你的评论。你能说得更详细些吗?请注意,类型为Action的属性没有问题。
@Caspar:这里应该发生的“魔力”是在编译时将一个操作转换为Action。我们不会试图将其视为动作或动作或其他任何东西,这取决于分配给它的运行时类型。“dynamic”只是穿着华丽衣服的“object”。整个问题的有趣之处在于,如果你通过一个泛型T传递dynamic
,它就会编译得很好。因此,publicinterface-IMyInterface{event Action OnSomeEvent;}
及其正确的实现是一个ns.IMyInterface=new class MyInterface()
编译,即使接口位于不同的程序集中。将动态
包装在T中与直接使用它不同/更严格??见我的答案,我详细阐述了它。
/** does build **/
IGenericBar<dynamic> f = new Foo3<dynamic>();
f.OnSomeEvent += new Action<dynamic>(f_OnSomeEvent);