Почему C # не разрешает наследование возвращаемого типа при реализации интерфейса - PullRequest
22 голосов
/ 24 августа 2009

Есть ли рациональная причина, по которой приведенный ниже код недопустим в C #?

class X: IA, IB
{
    public X test() // Compliation Error, saying that X is not IB
    {
        return this;
    }
}

interface IA 
{
    IB test();
}
interface IB { };

Ответы [ 6 ]

32 голосов
/ 24 августа 2009

Эта функция называется «ковариация возвращаемого типа». C # не поддерживает его по следующим причинам:

1) CLR не поддерживает его. Чтобы заставить его работать в C #, нам нужно было бы просто плюнуть на кучу маленьких вспомогательных методов, которые приводят к возвращаемому типу к нужной вещи. Ничто не мешает вам сделать это самостоятельно.

2) Андерс считает, что ковариация возвращаемого типа не является хорошей языковой особенностью.

3) \ У нас много высших приоритетов для языка. У нас только ограниченные бюджеты, и поэтому мы стараемся использовать только лучшие возможности, которые мы можем в любой данной версии. Конечно, это было бы хорошо, но это достаточно легко сделать самостоятельно, если хотите. Лучше, если мы потратим время на добавление функций, которые улучшат опыт разработчиков или добавят больше возможностей для представления языка.

16 голосов
/ 24 августа 2009

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

class  X : IA, IB
{
  public X test()
  {
    return this;
  }

  IB IA.test()
  {
    return this;
  }
}

interface IA
{
  IB test();
}

interface IB
{
}
5 голосов
/ 24 августа 2009

Подписи должны точно соответствовать тому, что указывает интерфейс. Нет причины, по которой вы не можете вернуть экземпляр X из метода, но сигнатура метода должна будет использовать IB.

Что касается рациональной причины ... это, вероятно, предпочтительнее с точки зрения читабельности кода.

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

3 голосов
/ 24 августа 2009

Потому что C # не поддерживает совместное использование и противоречие для интерфейсов во время компиляции Таким образом, реализация метода IA.Test () должна точно соответствовать его объявлению. Однако вы можете вернуть экземпляр X во время выполнения

1 голос
/ 22 сентября 2011

Это может помочь http://geekswithblogs.net/abhijeetp/archive/2010/01/10/covariance-and-contravariance-in-c-4.0.aspx Вы можете использовать ключевое слово "out"

1 голос
/ 24 августа 2009
public X test();

Вы должны объявить тело для всех методов любого класса, которые не являются абстрактными.

Попробуйте это:

class X : IA, IB
{
    public IB test()
    {
        return new X();
    }
}

interface IA
{
    IB test();
}
interface IB { };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...