Неявное преобразование при использовании условного оператора
У меня есть следующие классы:
abstract class AClass { }
class Foo : AClass { }
class Bar : AClass { }
И когда я пытаюсь их использовать:
AClass myInstance;
myInstance = true ? new Foo() : new Bar();
Этот код не будет компилироваться из-за "Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между" CSharpTest.Class1.Foo "и" CSharpTest.Class1.Bar "
Но следующие примеры скомпилировать ok:
if (true)
{
myInstance = new Foo();
}
else
{
myInstance = new Bar();
}
Это тоже нормально:
myInstance = true ? (AClass) new Foo() : new Bar();
или
myInstance = true ? new Foo() : (AClass) new Bar();
Почему существует такая большая разница в поведении условного оператора, и если предложение?
Ответы
Ответ 1
Это ожидаемое поведение.
Так как между X и Y не существует неявного преобразования (даже если у них есть общая база, между ними нет неявного преобразования), вам нужно явно указать (по крайней мере) один из них в базовый класс, чтобы неявный преобразование есть.
Подробное объяснение из спецификации С#:
Второй и третий операнды оператора ?:
управляют типом условного выражения. Пусть X и Y - типы второго и третьего операндов. Тогда,
Если X и Y являются одним и тем же типом, то это тип условного выражения.
В противном случае, если неявное преобразование (раздел 6.1) существует от X до Y, но не от Y до X, то Y является типом условного выражения.
В противном случае, если неявное преобразование (раздел 6.1) существует от Y до X, но не от X до Y, то X является типом условного выражения.
В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.
Ответ 2
На самом деле нет большой разницы в тройном операторе и в условии if, в отличие от ваших выражений.
В вашем первом рабочем примере вы конвертируете между Foo и AClass или Bar и AClass, что явно отлично.
Во втором рабочем примере вы говорите тернарному оператору посмотреть на AClass и Bar. В третьем рабочем примере вы говорите тернарному оператору взглянуть на Foo и AClass. Очевидно, что у них очевидные преобразования.
В нерабочем примере вы говорите ему, чтобы посмотреть на Foo и Bar. Там нет никакого неявного преобразования (потому что, например, один из них не получается из другого). Но вы можете идти дальше и быть откровенным в этом вопросе и использовать его (что вы делаете во 2-м и 3-м рабочих примерах), так как есть доступное преобразование.