Неоднозначный вызов между перегрузками двухсторонних неявных кастируемых типов, когда производный тип единицы передается в качестве параметра
(Попытка найти название, которое суммирует проблему, может быть очень сложной задачей!)
У меня есть следующие классы с некоторыми перегруженными методами, которые вызывают ошибку компилятора неоднозначности вызова:
public class MyClass
{
public static void OverloadedMethod(MyClass l) { }
public static void OverloadedMethod(MyCastableClass l) { }
//Try commenting this out separately from the next implicit operator.
//Comment out the resulting offending casts in Test() as well.
public static implicit operator MyCastableClass(MyClass l)
{
return new MyCastableClass();
}
//Try commenting this out separately from the previous implicit operator.
//Comment out the resulting offending casts in Test() as well.
public static implicit operator MyClass(MyCastableClass l)
{
return new MyClass();
}
static void Test()
{
MyDerivedClass derived = new MyDerivedClass();
MyClass class1 = new MyClass();
MyClass class2 = new MyDerivedClass();
MyClass class3 = new MyCastableClass();
MyCastableClass castableClass1 = new MyCastableClass();
MyCastableClass castableClass2 = new MyClass();
MyCastableClass castableClass3 = new MyDerivedClass();
OverloadedMethod(derived); //Ambiguous call between OverloadedMethod(MyClass l) and OverloadedMethod(MyCastableClass l)
OverloadedMethod(class1);
OverloadedMethod(class2);
OverloadedMethod(class3);
OverloadedMethod(castableClass1);
OverloadedMethod(castableClass2);
OverloadedMethod(castableClass3);
}
public class MyDerivedClass : MyClass { }
public class MyCastableClass { }
Следует отметить две очень интересные вещи:
Закомментирование любого из неявных операторных методов устраняет неоднозначность.Попытка переименовать первый перегруженный метод в VS приведет к переименованию первых четырех вызовов метода Test ()!Это, естественно, ставит два вопроса:
Какова логика, лежащая в основе ошибки компилятора (т.е. как компилятор пришел к неоднозначности)?Что-то не так с этим дизайном? Интуитивно понятно, что двусмысленности не должно быть, и вызывающий сбой вызов должен быть разрешен при первой перегрузке метода (OverloadedMethod(MyClass l, MyClass r)
) какMyDerivedClass
более тесно связан сMyClass
а не литье, но в остальном не имеет значенияMyCastableClass
, Кроме того, рефакторинг VS, похоже, согласен с этой интуицией.РЕДАКТИРОВАТЬ: После игры с рефакторингом VS я увидел, что VS сопоставляет вызов вызывающего метода с первой перегрузкой, определенной в коде, в зависимости от того, что это. Таким образом, если мы поменяемся местами между двумя перегрузками, VS сопоставит вызывающий вызов вызов сMyCastableClass
параметр. Вопросы все еще актуальны, хотя.