20

我正在学习来自 C++ 的 C# 并且遇到了障碍。

我有一个抽象类 AbstractWidget、一个接口 IDoesCoolThings 和一个派生自 AbstractWidget 的类,称为 RealWidget:

public interface IDoesCoolThings
{
    void DoCool();
}

public abstract class AbstractWidget : IDoesCoolThings
{
    void IDoesCoolThings.DoCool()
    {
        Console.Write("I did something cool.");
    }
}

public class RealWidget : AbstractWidget
{

}

当我实例化一个 RealWidget 对象并在其上调用 DoCool() 时,编译器给我一个错误说

“RealWidget”不包含“DoCool”的定义

我可以将 RealWidget 对象转换为 IDoesCoolThings,然后调用将起作用,但这似乎没有必要,而且我也失去了多态性(即使我定义了 RealWidget.DoCool(),AbstractWidget.DoCool() 也将始终被调用)。

我想解决方案很简单,但是我尝试了很多方法,但我一生都无法弄清楚这一点。

4

4 回答 4

42

您遇到问题是因为您使用了显式接口实现(EII)。当一个成员被显式实现时,它不能通过类实例访问——只能通过接口的实例。在您的示例中,这就是为什么您不能调用DoCool(),除非您将实例转换为IDoesCoolThings.

解决方案是DoCool()公开并删除显式接口实现:

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()      // DoCool() is part of the abstract class implementation.
    {
        Console.Write("I did something cool.");
    }
}

// ...

var rw = new RealWidget();
rw.DoCool();                  // Works!

通常,您在两种情况下使用 EII:

  • 您有一个必须实现两个接口的类,每个接口都包含一个成员,该成员与另一个接口中的另一个成员具有相同的名称/签名。
  • 您希望强制客户端不依赖于您的类的实现细节,而是依赖于您的类正在实现的接口。(有些人认为这是一种很好的做法。)
于 2009-03-26T02:03:33.717 回答
8

将您的声明更改为:

public abstract class AbstractWidget : IDoesCoolThings 
{
    public void DoCool()
    { 
        Console.Write("I did something cool."); 
    }
}
于 2009-03-26T02:04:18.957 回答
7

如果选择隐式实现接口,则实现接口的方式是显式实现 void IDoesCoolThings.DoCool()。

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()
    {
        Console.Write("I did something cool.");
    }
}

然后它将起作用。

读这个 :

C# 接口。隐式实现与显式实现

于 2009-03-26T02:04:38.833 回答
1

你应该这样做:

public interface IDoesCoolThings 
{
   void DoCool();
}

public abstract class AbstractWidget 
{
   public void DoCool()
   {
      Console.WriteLine("I did something cool.");
   }
}

public class Widget : AbstractWidget, IDoesCoolThings 
{
}

用法:

var widget = new Widget();
widget.DoCool();
于 2013-01-30T07:38:24.580 回答