Почему я не могу реализовать интерфейс таким образом?

Возможный дубликат:
Поддерживает ли С# поддержку ковариации типа типа?

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

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

public interface IMoop
{
    object Moop();
}

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

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

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

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

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

Ответ 1

С# не поддерживает ковариацию возвращаемого типа для целей реализации интерфейса или переопределения виртуального метода. См. Этот вопрос для деталей:

Поддерживает ли С# поддержку ковариации типа типа?

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

И С# поддерживает ковариацию возвращаемого типа при преобразовании метода, возвращающего ссылочный тип, в тип делегата, тип возврата которого является совместимым ссылочным типом. (И аналогичным образом он поддерживает контравариантность параметров параметров.)

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

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

для деталей.

Ответ 2

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

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

public object Moop()
{
    return "Some new string";
}

Ответ 3

Разумная работа:

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

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

Ответ 4

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

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

public class MoopImplementor : IMoop<string>
{
    public string Moop() { return ""; }
}

Ответ 5

Из Спецификация языка С#:

13.4.4 Отображение интерфейса

Для целей сопоставления интерфейсов член класса A соответствует элемент интерфейса B, когда:

  • A и B - это методы, а имя type и формальные списки параметров A и B идентичны.

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