Подтвердить что ты не робот

Неявное преобразование при использовании условного оператора

У меня есть следующие классы:

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();

Почему существует такая большая разница в поведении условного оператора, и если предложение?

4b9b3361

Ответ 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-м рабочих примерах), так как есть доступное преобразование.