为什么C#类可以隐式和明确地从一个接口继承?

时间:2008-10-31 10:23:20

标签: c# inheritance implicit explicit

今天我碰巧发现一个C#类可以以隐式和显式方式继承一个接口。这让我感到惊讶。如果C#以这种方式工作,那么当以不同方式引用时,一个实例的行为会有所不同。

interface IFoo
{
    void DoSomething();
}

class Foo : IFoo
{
    #region IFoo Members
    public void DoSomething()
    {
        Console.WriteLine("do something implicitly");
    }
    #endregion

    #region IFoo Members
    void IFoo.DoSomething()
    {
        Console.WriteLine("do something explicitly");
    }
    #endregion
}


        Foo f = new Foo();
        f.DoSomething();

        ((IFoo)f).DoSomething();

以上代码运行并输出

do something implicitly
do something explicitly

我认为这种C#设计会使行为不一致。也许强制一个C#类可以以隐式或expliict方式从一个接口继承,但不能同时从两个接口继承。

有没有理由为什么C#以这种方式设计?

5 个答案:

答案 0 :(得分:13)

实现接口的每个类在该类的成员和接口的成员之间都有映射。如果类显式实现了接口成员,那么显式实现将始终映射到接口。如果没有显式实现,则需要隐式实现,并且该实现将映射到接口。

当一个类具有相同的成员名称和相关类型作为接口时,它还显式实现了接口的相应成员,那么该类的“隐式”实现不是< / em>被认为是接口的实现(除非显式实现调用它)。

除了在每种情况下类具有相同成员名称/类型的多个接口的不同含义之外,即使只有一个接口,类本身也被认为具有可能的隐式接口与唯一的界面具有相同的成员/类型,但仍然意味着不同的东西。

答案 1 :(得分:11)

您的示例隐式和显式地实现IFoo。您只能显式实现IFoo.DoSometing()。您的类上有一个名为DoSomething()的新方法。它与IFoo.DoSomething无关,只是它具有相同的名称和参数。

答案 2 :(得分:7)

这使得它在发生碰撞时更加灵活。特别是,请查看IEnumeratorIEnumerator<T> - 它们都具有Current属性,但属性不同。你使用显式接口实现来实现它们(并且泛型形式扩展了非泛型形式)。

答案 3 :(得分:2)

多重继承: 如果从两个为不同目的定义相同方法的接口派生,该怎么办?

  interface IMoveable
  {
    public void Act();
  }

  interface IRollable
  {
    public void Act();
  }

  class Thing : IMoveable, IRollable
  {
    //TODO Roll/Move code here

    void IRollable.Act()
    {
      Roll();
    }

    void IMoveable.Act()
    {
      Move();
    }
  }

答案 4 :(得分:0)

伙计们,谢谢你的回答。

事实证明“C#类可以同时以隐式和显式两种方式继承一个接口”实际上是一种错觉。实际上,一个类可以一次继承一个接口。

在最初的问题中,“DoSomething”方法似乎是“隐式实现”接口IFoo(该方法实际上是由VS2008生成的),但实际上并非如此。通过显式实现接口IFoo,“DoSomething”方法变成了普通的方法,除了具有相同的签名外,与IFoo无关。

我仍然认为它是一个棘手的C#设计,很容易误用它。说,我有一些像这样的代码

        Foo f = new Foo();
        f.DoSomething();

现在,我想将它重构为下面的代码。看起来完全没问题,但执行结果不同。

        Action<IFoo> func = foo => foo.DoSomething();
        func(f);