【问题标题】:Compiler says I am not implementing my interface, but I am?编译器说我没有实现我的接口,但我是吗?
【发布时间】:2011-09-15 00:15:15
【问题描述】:

好的,我有两个命名空间。一个包含我的接口,一个包含实现类。像这样:

namespace Project.DataAccess.Interfaces
{
    public interface IAccount
    {
        string SomeMethod();
    }
}

namespace Project.DataAccess.Concrete
{
    class Account : Project.DataAccess.Interfaces.IAccount
    {
        string SomeMethod()
        {
            return "Test";
        }
    }
}

使用此代码我得到一个错误:

“Project.DataAccess.Concrete.Account”没有实现接口成员“Project.DataAccess.Interfaces.IAccount.SomeMethod”。 'Project.DataAccess.Concrete.Account.SomeMethod' 无法实现接口成员,因为它不是公共的

如果我将类和方法公开,它就可以正常工作。但是,如果我改为使用接口名称来限定方法名称,那也可以修复它。为什么?例如:

namespace Project.DataAccess.Concrete
{
    class Account : Project.DataAccess.Interfaces.IAccount
    {
        string IAccount.SomeMethod()
        {
            return "Test";
        }
    }
}

为什么这会解决它?如果我不这样做,为什么它必须公开?

要明确

我很清楚将其公开可以修复它。在不公开任何内容的情况下使方法签名看起来像这样:

string IAccount.SomeMethod()

为什么?

【问题讨论】:

标签: c# .net inheritance interface


【解决方案1】:

接口实现需要是公开的或显式的:

公开:

class Account : IAccount
{
    public string SomeMethod()
    {
        return "Test";
    }
}

显式:

class Account : IAccount
{
    string IAccount.SomeMethod()
    {
        return "Test";
    }
}

如果不指定访问修饰符,C# 中的默认访问修饰符是private

【讨论】:

  • 当然有趣的是,您不能为显式实现的接口指定任何访问修饰符。我很想知道为这些生成的 IL。我的意思是,它可以由外部类调用,但前提是您首先将其 cast 到该接口。这实际上很奇怪。 :)
  • 这真的很有用。我有划分应用程序层的接口,我绝不希望在没有接口的情况下使用它们。显式实现接口正是我需要做的:)
【解决方案2】:

在实现接口时,您有 2 个基本选项:隐式或显式。隐式实现采用公共方法或属性的形式,而显式采用以 IFoo. 修饰符开头的方法或属性的形式,否则不公开。

interface IFoo
{
    void Bar();
}

class FooA : IFoo
{
    public void Bar() { }
}

class FooB : IFoo
{
    void IFoo.Bar() { }
}

这里的区别在于FooA 的情况下,void Bar 是该类的公开可见 API 的一部分。代码可以通过类的实例调用Bar

FooA foo = new FooA(); 
foo.Bar(); // legal

FooB 的情况下,void Bar 不是该类的公开可见 API 的一部分。该方法仍然可以调用,但必须通过接口显式调用。

FooB foo = new FooB();
foo.Bar(); // not legal
IFoo myFoo = foo;
myFoo.Bar(); // legal

您的代码无法编译,因为它在隐式和显式接口实现之间的未知水域中行走。您看到通过您的更改,您已经合法地定义了一个显式实现,这就是该特定版本编译的原因。否则,您还发现需要 public 修饰符来编译非显式版本。

【讨论】:

    【解决方案3】:

    实现接口的方法需要公开。在您的后一种情况下,您将明确声明它。这就是specification says 关于显式接口实现的内容。

    显式接口成员 实现有不同 可访问性特征比 其他成员。因为显式 接口成员实现是 永远无法通过他们的充分访问 方法调用中的限定名称 或属性访问,它们位于 感觉私密。然而,由于他们可以 通过接口访问 例如,它们在某种意义上也是 公开。

    【讨论】:

      【解决方案4】:

      'Project.DataAccess.Concrete.Account.SomeMethod' 无法实现接口成员因为它不是公共的

      namespace Project.DataAccess.Concrete
      {
          public class Account : IAccount    
          {
              public string IAccount.SomeMethod()
              {
                  return "Test";
              }
          }
      }
      

      【讨论】:

      • 正如我特别指出的那样。将其公开修复它,但为什么指定 IAccount.SomeMethod 而不公开修复它呢?
      • 大概因为接口成员必须是公共的,所以当它被显式声明时,编译器足够聪明,知道将其公开,但如果你没有显式地将它绑定到 IAccount,编译器就不会确定您不是指其他“SomeMethod()”
      【解决方案5】:

      你没有在你的类声明中提到你将实现IAccount

      您的类声明应如下所示:

      class Account : IAccount
      { 
        //Implementation here.
      }
      

      另外,您正在使用Account 的“默认”保护级别,并且该保护级别不是“公共”,而是一个接口 (IAccount) 默认定义公共方法。

      因此,当您在类和方法名称前加上public 时,您实际上是在实现接口。同样,当您将SomeMethod 声明为

      IAccount.SomeMethod()
      {
         //Implementation Here
      }
      

      你正在做的是显式实现接口。

      【讨论】:

        【解决方案6】:

        我认为用string IAccount.SomeMethod() 明确声明它是可行的,因为.NET 知道该方法的实现只能通过接口访问,因此它继承了接口的公共可见性。换句话说,既然你明确说它是一个接口成员,编译器可以暗示它必须是公共的,所以你不必重新陈述显而易见的。

        这也在这里讨论:http://msdn.microsoft.com/en-us/library/aa664591%28v=vs.71%29.aspx

        这是一个编译时错误 显式接口成员 实现包括访问 修饰符,它是一个编译时 包含修饰符的错误 抽象、虚拟、覆盖或 静态的。

        显式接口成员 实现有不同 可访问性特征比 其他成员。因为显式 接口成员实现是 永远无法通过他们的充分访问 方法调用中的限定名称 或属性访问,它们位于 感觉私密。然而,由于他们可以 通过接口访问 例如,它们在某种意义上也是 公开。

        【讨论】:

          【解决方案7】:
          class Account : IAccount    
              {         
              public string SomeMethod()         
              {            
               return "Test";         
              }     
              } 
          

          告诉你的类实现接口。使用 Interface.Method 名称显式实现该方法(但我不确定为什么或如何),您需要将它们公开。

          当类已经有同名成员时,您想使用 Interface.Method 显式实现接口要求

          class MyClass : IAccount
          {
             public int SomeMethod() {}
             public string IAccount.SomeMethod() {}
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-07
            • 1970-01-01
            • 2019-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多