2017-01-28 10 views
1

Если у меня есть 2 метода с тем же именем, но с разными типами возврата. Они наследуются классом из двух интерфейсов. Этот класс может обеспечить 1 реализацию для обоих, если тип возврата для реализации соответствует типу возврата в обоих интерфейсах.То же имя в двух методах в двух разных интерфейсах, почему бы не реализовать 1?

Например, String тип реализует оба метода: IEnumerable и IEnumerable<char>. Реализация для типа String содержит только одну реализацию для GetEnumerator.

public CharEnumerator GetEnumerator(); 

Я считаю, что это возможно, потому что CharEnumerator реализует как IEnumerator и IEnumerator<char>

public CharEnumerator: IEnumerator, IEnumerator<char> 

Однако, подобный код в моем приложении ниже дает мне ошибку компиляции,

interface Ia { IEnumerator o();} 
interface Ib { IEnumerator<int> o();} 
class e : IEnumerator, IEnumerator<int>{} 
class c : Ia, Ib { public e o() { return new e(); } } 

Если я сделайте F12 по типу String в Visual Studio, я вижу что-то вроде ниже, enter image description here

Как вы можете видеть, есть только одна неявная реализация GetEnumerator(), нет явных реализаций там

+2

C# язык не поддерживает тип возвращаемого значения ковариационной , Вот почему класс String имеет * два метода GetEnumerator(). Второй - это явный метод реализации, необходимый для избежания двусмысленности. И почему вам нужны и два. –

+0

@HansPassant Я думаю * оба интерфейса реализованы явно. 'string.GetEnumerator' фактически возвращает' CharEnumerator', который не будет соответствовать ни одному из двух интерфейсных контрактов. Я предполагаю, что это устаревший код из C# 1 – InBetween

+0

@HansPassant Почему тогда мой код не скомпилирован, тип 'e' происходит от' IEnumerable', а также 'IEnumerable <>' – EagerToLearn

ответ

2

Строка не неявно реализации IEnumerable или IEnumerable<char>. Он делает это явно, что означает, что вы можете обращаться к методам только с помощью ссылки IEnumerable или IEnumerable<char>.

Метод CharEnumerator GetEnumerator() не использует ни интерфейс, поскольку тип возврата не является IEnumerator или IEnumerator<T>; CharEnumerator является одним из возможных IEnumerator, но интерфейс запрашивает любойIEnumerator.

Явные интерфейсы очень полезны, вы только что наткнулись на одну из функций, которые они предоставляют; внедрение в один класс различных интерфейсов, которые определяют метод с тем же именем:

interface IFoo 
{ 
    IFoo Frob(); 
} 

interface IBar 
{ 
    IBar Frob(); 
} 

public class Blah: IFoo, IBar 
{ 
    Foo IFoo.Frob() => new Foo(); 
    Bar IBar.Frob() => new Bar(); 
    void Frob(); 
} 

И сейчас, вы получите следующее поведение:

var b = new Blah(); 
b.Frob(); //returns nothing, this method is not implementing any of the two interfaces. 
(b as IBar).Frob(); //returns a bar 
(b as IFoo).Frob(); //returns a foo 
+0

См. Отредактированный вопрос выше. Visual Studio показывает только одну неявную реализацию GetEnumerator() – EagerToLearn

+0

@EagerToLearn Нет, это не подразумеваемая реализация. 'CharEnumerator GetEnumerator()' не реализует * никакого * интерфейса. См. Изменения в моем примере, чтобы увидеть аналогичную ситуацию. Явные реализации не отображаются при проверке определения типа. – InBetween

+0

Получил это.Таким образом, строка предоставляет 'CharEnumerator GetEnumerator()' в дополнение к 2 явным реализациям, по одному для каждого 'IEnumerable' и' IEumerable '. Но почему бы не просто сделать 'IEnumerable.GetEnumerator()' явным, то создав 'IEnumerable .GetEnumerator()' available? – EagerToLearn

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

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