Подтвердить что ты не робот

Почему класс С# наследует от одного интерфейса как неявно, так и явно?

Сегодня я обнаружил, что один класс С# может наследовать один интерфейс как неявным, так и явным образом. Это меня удивляет. Если С# работает таким образом, то один экземпляр может вести себя по-разному, если ссылается по-разному.

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

Я считаю, что этот дизайн С# делает непоследовательность поведения. Возможно, что один класс С# может наследовать от одного интерфейса неявным или эксплицитным способом, но не тем и другим.

Есть ли причина, почему С# сконструирован таким образом?

4b9b3361

Ответ 1

В вашем примере не реализует IFoo как неявно, так и явно. Вы явно реализуете IFoo.DoSometing(). У вас есть новый метод в вашем классе под названием DoSomething(). Это не имеет никакого отношения к IFoo.DoSomething, за исключением того, что у него одинаковое имя и параметры.

Ответ 2

Каждый класс, реализующий интерфейс, имеет сопоставление между этими членами класса и членами интерфейса. Если класс явно реализует элемент интерфейса, то явная реализация будет отображать всегда в интерфейс. Если не существует явной реализации, ожидается неявная реализация, и она будет отображена на интерфейс.

Если класс имеет одно и то же имя участника и связанные с ним типы в качестве интерфейса , но, он также явно реализует соответствующий элемент для интерфейса, тогда реализация класса "неявное" не рассматривается как реализация интерфейс вообще (если только явная реализация не вызывает его).

В дополнение к различным значениям в каждом случае, когда класс реализует несколько интерфейсов с одинаковыми именами/типами элементов, даже с одним интерфейсом, сам класс считается неявным интерфейсом, который может иметь одинаковые элементы/типы, такие как единственный интерфейс, но все же означает что-то другое.

Ответ 3

Это делает его более гибким, когда возникают столкновения. В частности, посмотрите IEnumerator и IEnumerator<T> - они оба имеют свойство Current, но разных типов. Вы должны использовать явную реализацию интерфейса для реализации обоих (и общая форма расширяет не-общую форму).

Ответ 4

Множественное наследование: Что делать, если вы извлекаете из двух интерфейсов, определяющих один и тот же метод для разных целей?

  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

Ребята, спасибо за ваши ответы.

Оказывается, что "класс С# может наследовать один интерфейс как неявным, так и явным образом в одно и то же время" на самом деле является иллюзией. На самом деле один класс может наследовать один интерфейс за один раз.

В исходном вопросе метод "DoSomething" кажется "неявно реализуемым" интерфейсом IFoo (метод фактически генерируется VS2008), но на самом деле это НЕ. С явной реализацией интерфейса IFoo метод "DoSomething" превращается в обычный метод, который не имеет ничего общего с IFoo, кроме одной и той же сигнатуры.

Я все еще считаю, что это сложный дизайн С#, и его легко использовать ошибочно. Скажем, у меня есть код вроде этого

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

Теперь я хочу реорганизовать его ниже кода. Кажется, все в порядке, но результат выполнения отличается.

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