21

我偶然发现了 C# 的这个“特性”——实现接口方法的基类不必从它派生

例子:

public interface IContract
{
    void Func();
}

// Note that Base does **not** derive from IContract
public abstract class Base
{
    public void Func()
    {
        Console.WriteLine("Base.Func");
    }
}

// Note that Derived does *not* provide implementation for IContract
public class Derived : Base, IContract
{
}

发生的事情是Derived神奇地选择了一个公共方法Base.Func,并决定它会实现IContract.Func

这种魔法背后的原因是什么?

恕我直言:这种“准实现”功能非常不直观,并且使代码检查更加困难。你怎么看?

4

2 回答 2

35

原因是您的评论完全不正确:

// 注意 Derived 不提供IContract 的实现

当然可以。遵循逻辑。

  • Derived 需要提供一个与 IContract 的每个成员对应的公共成员。
  • 基类的所有可继承成员也是派生类的成员;这就是继承的定义
  • 因此 Derived 提供了 IContract 的实现;它继承的成员是满足要求的成员
  • 因此,没有错误。

此功能非常不直观,并且使代码检查更加困难。你怎么看?

我认为如果您不喜欢该功能,则不应使用它。如果您发现阅读使用此功能的代码感到困惑和奇怪,请鼓励使用此功能的同事停止这样做。

此功能与使用派生类中的基类方法的任何其他功能有何不同?有许多不同的方式可以在派生类中使用或提及来自基类的方法——方法调用、覆盖、方法组转换等。

此外,这是一个相对简单、直接的案例。如果你真的想抱怨 C# 中令人困惑的接口语义,我会花时间抱怨接口重新实现语义。那是真正似乎在烤人的面条。我总是必须在规范中查找那个东西,以确保我得到了正确的语义。

于 2010-05-31T15:15:59.380 回答
12

为什么你认为这很奇怪和不自然?基类的每个公共成员也是派生类的公共成员。所以这里没有矛盾。无论如何,如果您愿意,您可以显式地实现接口。

于 2010-05-31T10:06:03.180 回答