当接口和具体位于不同的项目中时,“无法实现接口成员”错误

本文关键字:接口 成员 错误 实现 于不同 项目 | 更新日期: 2023-09-27 17:55:58

编译:

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

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

访问 'TestProject2.MyInterface.OnSomeEvent.remove' 无法实现接口成员 "InterfaceNamespace.IMyInterface.remove_OnSomeEvent(系统.操作)" 对于类型"TestProject2.MyInterface"。 使用显式接口 实现。

这只发生在动态参数...

当接口和具体位于不同的项目中时,“无法实现接口成员”错误

很好的收获。这看起来可能是 C# 编译器中的一个错误 - 我会 ping Eric Lippert 看看他的想法。(dynamic可能有点棘手;这个错误很可能有一个非常好但不明显的原因。

编辑:下面的代码似乎根本不起作用我可以发誓我今天早上让它工作......我对发生了什么感到非常困惑。根据西蒙的评论,代码失败,并显示一条消息,指出该语言不支持它。

请注意,如果您确实使用显式接口实现,它似乎可以很好地编译:

// 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;

它给出以下错误消息:

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

如果您只是尝试更改为事件访问器语法,则会收到与原始代码。

请注意,将事件更改为属性适用于自动实现的属性实现。

感谢您发布此问题,并感谢 Jon 以我的方式发送它。我已将其放入我们专门研究"动态"的测试人员之一的调查队列中。我们将看看我们是否可以弄清楚这里发生了什么。它闻起来肯定像虫子。

将来,请考虑在 connect.microsoft.com 上发布这样的东西;这样可以更快地将其发送给测试人员,并为我们提供更好的机制来获取有关该问题的更多信息。

这个答案是为了表达我对这个有趣问题的想法。不是真正的答案,而是对整个讨论的贡献,对于普通评论来说太小了。

我检查了一些东西,这个界面:

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; }
    }
}

永远不会起作用,似乎一个规则排除了另一个必要的规则。

但是.. 如果我们调用泛型寻求帮助,并使用 Type 参数而不是直接使用 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; }
    }
}

出于某种原因,我们可以构建(应该)并运行:

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

似乎类型参数做了一些编译器满意的额外操作。

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

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

但目前我把我的两分钱放在类型比较必须有通过添加/删除访问器进行包含事件的目标/方法。

我敢打赌编译器落在它不能保证什么的问题dynamic 位于外部程序集中,因此无法确定元素是否已在列表中,这是添加或删除它们所必需的。(因此显式接口实现)

我们都知道这只是其中的一部分属性对象,但似乎仍然它需要一个额外的步骤,其中一些强型是有保证的,那就是T 在编译时做什么。

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