2008-10-31 12 views
16

Сегодня я обнаружил, что один класс C# может наследовать один интерфейс как неявным, так и явным образом. Это меня удивляет. Если 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# может наследовать один интерфейс неявным или эксплицитным способом, но не тот и другой.

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

+0

Я не заметил, что вы можете сделать то и другое. Это кажется немного глупым ... – 2008-10-31 10:26:41

+0

Это не глупо. Прочтите ответы. – 2008-10-31 10:39:25

+0

Извините, что я дважды пытаюсь добавить «явный интерфейс-член-реализация» в качестве тега (это имя используемой функции), но, видимо, этот тег будет слишком длинным. :) – Rytmis 2008-10-31 11:11:03

ответ

11

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

13

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

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

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

+0

Является ли этот неявный интерфейс фактическим интерфейсом или просто классом, отображающим интерфейс, т. Е. Является ли он типом, хотя и скрытым? – ProfK 2008-10-31 13:18:51

+0

Я просто ссылаюсь на все, что предоставляет класс. CLR не отличается между реализацией класса и его встроенным интерфейсом (т. Е. Вы не можете реализовать интерфейс другого класса и заменить его, если интерфейс не является отдельно определенным типом интерфейса). – 2008-10-31 16:20:33

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

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

0

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

Получается, что «класс C# может наследовать один интерфейс как неявным, так и явным образом в то же время» - на самом деле иллюзия. На самом деле один класс может наследовать один интерфейс за один раз.

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

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

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^