Нет предупреждения или ошибки (или сбоя во время выполнения), когда противоречивость приводит к неоднозначности
Во-первых, помните, что .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
Статус до открытия награды: Три ответа от двух пользователей.
Статус в последний день щедрости: Новые ответы пока не получены. Если ответов не будет, мне нужно будет наградить Мусульманина Бен Дау.