Вопрос по c# – Почему я не могу реализовать интерфейс таким образом? [Дубликат]

12

Possible Duplicate:
Does C# support return type covariance?

Я не уверен, что я просто глупый ...

Если у меня есть интерфейс:

public interface IMoop
{
    object Moop();
}

Почему я не могу реализовать это так (полагаю, это будет использовать неявную ковариацию?)

public class MoopImplementor : IMoop
{
    string Moop();
}

Любой экземпляр MoopImplementor будет соответствовать контракту, указанному IMoop, поэтому кажется, что все должно быть в порядке.

Пожалуйста, просветите меня :)

РЕДАКТИРОВАТЬ: чтобы быть ясным - так как реализующий класс возвращает что-то, что наследует от типа возврата метода Interfaced - я чувствую, что это должно работать. В частности,string Являетсяobject, (и то же самое касается любой другой цепочки наследования).

@ kailoon нет, это не так. Контракт позволяет вам вернуть целое число в штучной упаковке как Объект, но не целое число. Это разные. Chris Shain
Технически контракт также позволяет мне вернуть Integer, чего нет в вашей реализации. kailoon
Да, я понимаю это. но ПОЧЕМУ это вопрос :) Dave Bish
Относительно вашего редактированияI feel this should work - Я чувствую, что люди должны давать мне свободные деньги, но это не так. asawyer
@Dave: компилятор здесь строгий. Вам нужно сделатьMoop() явно вернутьobjectв противном случае вы не реализуете интерфейс. Это не проблема, потому что вы можете просто вернутьstring из метода, как вы правильно заметили. Niklas B.

Ваш Ответ

5   ответов
13

C # не поддерживаетreturn type covariance для реализации интерфейса или переопределения виртуального метода. Смотрите этот вопрос для деталей:

Поддерживает ли C # ковариацию типа возвращаемого значения?

C # поддерживаетgeneric covariance and contravariance of interfaces and delegate types that are constructed wtih reference types for the type arguments по состоянию на C # 4.

И C # поддерживаетreturn type covariance когдаconverting a method that returns a reference type to a delegate type whose return type is a compatible reference type. (И аналогично он поддерживает тип параметраcontravariance.)

Если эта тема вас интересует, я написал множество статей, в которых обсуждаются различные варианты отклонений, которые C # поддерживает и не поддерживает. Увидеть

https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/

для деталей.

Черт возьми, ты не шутишь - 11 сообщений в блоге о дисперсии. Там проходит весь мой день :) Dave Bish
3

Вы не выполняете контракт. Тем не менее, вы можете сделать это с помощью дженериков:

public interface IMoop<T>
{
    T Moop();
}

public class MoopImplementor : IMoop<string>
{
    public string Moop() { return ""; }
}
@NiklasB. Я согласен, это другое дело.
Это другое дело.
@Dave Ответ - вы не выполняете контрактные обязательства интерфейса в своей реализации. Сделай это по-другому.
@asawyer: +1 за хороший ответ
Извините - это был не вопрос. Dave Bish
2

ОтСпецификация языка C #:

13.4.4 Interface mapping

For purposes of interface mapping, a class member A matches an interface member B when:

  • A and B are methods, and the name, type, and formal parameter lists of A and B are identical.

Обратите внимание, что это ничего не говорит о наследовании или конвертируемости! Тип возврата должен быть идентичным.

Хотя это и неплохо, в нем ничего не говорится об обосновании этого :)
7

Поскольку интерфейс указывает, что метод ДОЛЖЕН вернутьobject,string может наследовать отobject, но интерфейс определяет метод, который возвращает гораздо более общий тип.

Имейте в виду, однако, что ничто не мешает вам сделать следующее:

public object Moop()
{
    return "Some new string";
}
но строка это объект. Dave Bish
@NiklasB. Вопрос, который разместил Дейв, «почему так». Полагаю, что вы сказали, что ответ "он такой, какой он есть". Для меня это не похоже на хороший ответ. Возможно, Jon Skeet рассмотрит вопрос о том, есть ли причина, по которой C # не позволяет этого сделать
Везде, где я использую это как интерфейс - «строка» или что-либо еще будет соответствовать договору «быть объектом». Dave Bish
@Dave: Вот почему у нас есть специализированные интерфейсы: p (хотя я понимаю вашу точку зрения)
@Dave: Ваше мнение не имеет значения. Это так, как есть. Какова ваша точка зрения?
4

Разумный обходной путь:

public class MoopImplementor : IMoop {
  public string Moop() { ... }
  object IMoop.Moop() { return Moop(); }
}

Это позволяет публичную реализацию наMoopImplementor иметь более точный тип, в то же время выполняя требования интерфейса.

Это всегда беспокоило меня. конкретноIEnumerable и другие. Но я думаю, что мы должны делать то, что должны.

Похожие вопросы