The_Unknown_Member Ответов: 2

C# почему тернарный оператор требует явного приведения?


Зачем мне нужен явный бросок в этом случае:
class Program
    {

        static void Main()
        {
            bool boolVal = true;
            Animal a = boolVal ? new Dog() : new Cat();
        }

    }

    class Animal { }

    class Dog : Animal { }

    class Cat : Animal { }



В этой строке: "животное a = boolVal ? new Dog() : new Cat();" я получу ошибку компилятора "тип условного выражения не может быть определен, потому что нет явного преобразования между Dog и Cat".
Но если я добавлю приведение к животному перед "new Dog ()", компилятор не будет жаловаться. Разве мне не нужно также использовать второе выражение ? Что это за странное поведение? :головная боль:

То же самое относится и к типам значений:
static void Main()
        {
            bool randomBool = true;
            short someRandomVal = 5;

            short s = randomBool ? someRandomVal : 0; // Won't work
        }


Однако здесь мне нужно привести второе значение, а не первое, потому что первое уже короткое.

Что я уже пробовал:

Однако, глядя на документацию для тернарного оператора, я не увидел там ничего, связанного с этим поведением.

0x01AA

Это вы найдете в разделе замечание в MS Docs:
"Либо типы first_expression и second_expression должны быть одинаковыми, либо должно существовать неявное преобразование из одного типа в другой."

0x01AA

Кстати, оба они будут компилироваться:
Животное а = булвал ? (Животное)Собака() : новый кот();
Животное а = булвал ? новая собака() : (животное)новая кошка();

2 Ответов

Рейтинг:
18

Mehdi Gholam

Скорее всего это недостаток процессора компилятора, т. е. компилятор принимает одну сторону ':' в качестве выходного типа (вероятно, левую) и предполагает, что вторая (правая) должна соответствовать в противном случае выбрасывает и ошибку без проверки дерева наследования в случае Dog и Cat и левая сторона этого выражения является Animal.

Во втором случае s это short но значение 0 предполагается равным int по умолчанию вы получаете исключение приведения.


The_Unknown_Member

Происходит ли такое поведение только с тернарными операторами?

Mehdi Gholam

- Не могу сказать.

BillWoodruff

"Скорее всего это недостаток процессора компилятора,"

Скорее всего по замыслу :)

Рейтинг:
0

BillWoodruff

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

Они работают потому что компилятор может определить что преобразование возможно:

bool boolVal = true;
Animal a1 = boolVal ? new Dog() : (Animal) new Cat();
Animal a2 = boolVal ? (Animal) new Dog() : new Cat();
В вашем примере с использованием типа 'short: то, что вы наблюдаете, частично связано с тем, что 'short не имеет литерального символа, который можно добавить к нему для обозначения типа, как это позволяют другие интегральные типы ... как "у" или "у" Для Уинта или Улонга: [^].

Эта работа:
bool randomBool = true;
short someRandomVal = 5;

var s1 = randomBool ? 0 : someRandomVal; // return Type is Int32

var s2 = randomBool ? someRandomVal : 0; // return Type is Int32

short s3 = randomBool ? someRandomVal : (short) 0; // return Type is Int16

Int32 s4 = randomBool ? someRandomVal : 0;
Int32 s5 = randomBool ? 0 : someRandomVal;
Имейте в виду, что интегральное числовое значение всегда может быть преобразовано/представлено в/в интегральном типе с "большей точностью" ... то есть больше битов, больший диапазон ... без потери информации.


Mehdi Gholam

5 ЕД

BillWoodruff

Спасибо, Мехди !