Нет предупреждения или ошибки (или сбоя во время выполнения), когда противоречивость приводит к неоднозначности

Во-первых, помните, что .NETString это обаIConvertible а также .ICloneable

Теперь рассмотрим следующий довольно простой код:

//contravariance "in"
interface ICanEat where T : class
{
  void Eat(T food);
}

class HungryWolf : ICanEat, ICanEat
{
  public void Eat(IConvertible convertibleFood)
  {
    Console.WriteLine("This wolf ate your CONVERTIBLE object!");
  }

  public void Eat(ICloneable cloneableFood)
  {
    Console.WriteLine("This wolf ate your CLONEABLE object!");
  }
}

Затем попробуйте следующее (внутри некоторого метода):

ICanEat wolf = new HungryWolf();
wolf.Eat("sheep");

Когда кто-то компилирует это, он получаетнет ошибка или предупреждение компилятора. Когда он запускается, похоже, что вызываемый метод зависит от порядка списка интерфейсов в моемclass декларация дляHungryWolf, (Попробуйте поменять местами два интерфейса через запятую (,разделенный список.)

Вопрос прост:не должен»это дает предупреждение во время компиляции (или бросить во время выполнения)?

Я, вероятно, не первый, кто придумал такой код. я использовалконтрвариантность интерфейса, но вы можете сделать полностью аналогичный пример сcovarainace интерфейса. И на самом делеМистер Липперт сделал именно это давным давно. В комментариях в своем блоге почти все согласны с тем, что это должно быть ошибкой. И все же они позволяют это молча.Зачем?

---

Расширенный вопрос:

Выше мы использовали этоString это обаIconvertible (интерфейс) иICloneable (интерфейс). Ни один из этих двух интерфейсов не является производным от другого.

Сейчас здесьПример с базовыми классами, в некотором смысле немного хуже.

Помните, чтоStackOverflowException это какSystemException (прямой базовый класс) иException (базовый класс базового класса). Тогда (еслиICanEat как раньше)

class Wolf2 : ICanEat, ICanEat  // also try reversing the interface order here
{
  public void Eat(SystemException systemExceptionFood)
  {
    Console.WriteLine("This wolf ate your SYSTEM EXCEPTION object!");
  }

  public void Eat(Exception exceptionFood)
  {
    Console.WriteLine("This wolf ate your EXCEPTION object!");
  }
}

Проверьте это с:

static void Main()
{
  var w2 = new Wolf2();
  w2.Eat(new StackOverflowException());          // OK, one overload is more "specific" than the other

  ICanEat w2Soe = w2;    // Contravariance
  w2Soe.Eat(new StackOverflowException());       // Depends on interface order in Wolf2
}

По-прежнему нет предупреждений, ошибок или исключений. По-прежнему зависит от порядка списка интерфейсов вclass декларация. Но причина, почему я так думаюХуже того, на этот раз кто-то может подумать, что разрешение перегрузки всегда будетSystemException потому что это'более конкретный, чем просто.Exception

Статус до открытия награды: Три ответа от двух пользователей.

Статус в последний день щедрости: Новые ответы пока не получены. Если ответов не будет, мне нужно будет наградить Мусульманина Бен Дау.

Ответы на вопрос(4)

Ваш ответ на вопрос