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

时间:2022-09-02 09:29:05

Today I happens to find that one C# class can inherit one interface both in implicit and explicit way. This surprises me. If C# works in this way, then one instance can behave differently when referenced in different way.

今天我碰巧发现一个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();

Above code runs and output

上面的代码运行和输出

do something implicitly
do something explicitly

I believe that this design of C# make inconsistency of behavior. Perhaps it is mandatory that one C# class can inherit from one interface in implicit or expliict way, but not both.

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

Is there any reason that why C# is designed in such a way?

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

5 个解决方案

#1


11  

Your example does not implement IFoo both implicitly and explicitly. You only implement IFoo.DoSometing() explicitly. You have a new method on your class called DoSomething(). It has nothing to do with IFoo.DoSomething, except that it has the same name and parameters.

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

#2


13  

Every class that implements an interface has a mapping between that class's members and the interface's members. If the class explicitly implements an interface member, then the explicit implementation will always be mapped to the interface. If there isn't an explicit implementation then an implicit implementation is expected, and that one will be mapped to the interface.

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

When a class has the same member name and associated types as an interface but it also explicitly implements the corresponding member for the interface, then the class's "implicit" implementation isn't considered an implementation of the interface at all (unless the explicit implementation calls it).

当一个类具有与接口相同的成员名称和关联类型但它也显式实现了接口的相应成员时,该类的“隐式”实现根本不被视为接口的实现(除非显式实现调用它)。

In addition to different meanings in each case where the class implements multiple interfaces with the same member name/types, even with only one interface, the class itself is considered to have an implicit interface which might have the same member/types as the sole interface but still mean something different.

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

#3


7  

This makes it more flexible for when there are collisions. In particular, look at IEnumerator and IEnumerator<T> - they both have a Current property, but of different types. You have to use explicit interface implementation in order to implement both (and the generic form extends the non-generic form).

这使得它在发生碰撞时更加灵活。特别是,看看IEnumerator和IEnumerator - 它们都有一个Current属性,但是有不同的类型。您必须使用显式接口实现才能实现这两者(并且泛型形式扩展了非泛型形式)。

#4


2  

Multiple inheritance : What if you derive from two interfaces defining same method for different purposes?

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

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

#5


0  

Guys, Thanks for your answers.

伙计们,谢谢你的回答。

It turns out that "C# class can inherits one interface in both implicit and explicit way at same time" is actually a illusion. Actually, one class can inherit one interface for one time.

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

In the original question, the "DoSomething" method seems "implicitly implement" interface IFoo (the method is actually generated by VS2008), but it is actually NOT. With explicit implementation of interface IFoo, the "DoSomething" method turns to be just normal method which has nothing to do with IFoo except with same signature.

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

I still believe it is a tricky design of C#, and it is easy to use it mistakenly. Say, I have some code like this

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

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

Now, I want to refactor it to below code. It seems perfectly OK, but the execution result is different.

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

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

#1


11  

Your example does not implement IFoo both implicitly and explicitly. You only implement IFoo.DoSometing() explicitly. You have a new method on your class called DoSomething(). It has nothing to do with IFoo.DoSomething, except that it has the same name and parameters.

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

#2


13  

Every class that implements an interface has a mapping between that class's members and the interface's members. If the class explicitly implements an interface member, then the explicit implementation will always be mapped to the interface. If there isn't an explicit implementation then an implicit implementation is expected, and that one will be mapped to the interface.

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

When a class has the same member name and associated types as an interface but it also explicitly implements the corresponding member for the interface, then the class's "implicit" implementation isn't considered an implementation of the interface at all (unless the explicit implementation calls it).

当一个类具有与接口相同的成员名称和关联类型但它也显式实现了接口的相应成员时,该类的“隐式”实现根本不被视为接口的实现(除非显式实现调用它)。

In addition to different meanings in each case where the class implements multiple interfaces with the same member name/types, even with only one interface, the class itself is considered to have an implicit interface which might have the same member/types as the sole interface but still mean something different.

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

#3


7  

This makes it more flexible for when there are collisions. In particular, look at IEnumerator and IEnumerator<T> - they both have a Current property, but of different types. You have to use explicit interface implementation in order to implement both (and the generic form extends the non-generic form).

这使得它在发生碰撞时更加灵活。特别是,看看IEnumerator和IEnumerator - 它们都有一个Current属性,但是有不同的类型。您必须使用显式接口实现才能实现这两者(并且泛型形式扩展了非泛型形式)。

#4


2  

Multiple inheritance : What if you derive from two interfaces defining same method for different purposes?

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

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

#5


0  

Guys, Thanks for your answers.

伙计们,谢谢你的回答。

It turns out that "C# class can inherits one interface in both implicit and explicit way at same time" is actually a illusion. Actually, one class can inherit one interface for one time.

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

In the original question, the "DoSomething" method seems "implicitly implement" interface IFoo (the method is actually generated by VS2008), but it is actually NOT. With explicit implementation of interface IFoo, the "DoSomething" method turns to be just normal method which has nothing to do with IFoo except with same signature.

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

I still believe it is a tricky design of C#, and it is easy to use it mistakenly. Say, I have some code like this

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

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

Now, I want to refactor it to below code. It seems perfectly OK, but the execution result is different.

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

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