Поведение тернарного оператора в C #

Недавно я наткнулся на следующие строки кода.

public class Program
    {      
      public static void Main(string[] args)
        {
          char x = 'X';
           int i = 0;
          Console.WriteLine (true  ? x : 0);
          Console.WriteLine(false ? i : x); 
        }
    }

Насколько мне известно, приведенный выше код должен выводить символ «X» в обоих случаях; Однако, когда я выполняю код, в консоли отображается 88; Может ли кто-нибудь помочь мне понять, почему вывод - это код ASCII, а не символ?


person Harry    schedule 29.02.2020    source источник
comment
Nitpick: это условный оператор. Тернар просто означает, что есть три операнда   -  person Hans Kesting    schedule 29.02.2020


Ответы (3)


Тернарный оператор имеет собственный тип. Это не всегда совпадает с типом двух операндов, которые вы передаете в оператор. Вместо этого это тип, в который могут преобразовываться обе ветви. В этом случае char имеет неявное преобразование в int. Это означает, что тип тернарных операторов int. См. Пример ниже. Оператор (true ? x : 0).GetType() показывает, что весь тернарный оператор имеет тип int.

public class Program
    {      
      public static void Main(string[] args)
        {
          char x = 'X';
          int i = 0;

          // Prints X fine
          Console.WriteLine(x);

          // Prints System.Int32
          Console.WriteLine((true ? x : 0).GetType());

          // Both print 88 - the int value of 'X'
          Console.WriteLine(true ? x : 0);
          Console.WriteLine(false ? i : x); 
        }
    }

"Почему" компилятор выбирает int, а не char, немного сложнее. C # spec определяет, что char неявно конвертируется в ushort, int, uint, long, float, double и decimal. В нем также говорится, что любой числовой тип явно преобразуется в char. Это ключевое отличие. Поскольку преобразование из char в int является неявным (оно не требует преобразования), компилятор использует его для тройного преобразования и игнорирует возможное преобразование в другом направлении. Подробнее о правилах определения типа тернарного оператора можно узнать здесь.

person just.another.programmer    schedule 29.02.2020
comment
Не могли бы вы сообщить мне, почему int не преобразуется в char вместо преобразования char в int? - person Harry; 29.02.2020
comment
@ Гарри: Потому что каждый char может быть int, но не каждый int может быть char. Один тип данных больше другого. - person David; 29.02.2020
comment
@ Гарри - Две причины. Один - .NET предпочитает int в качестве числового типа по умолчанию; когда две вещи необходимо преобразовать в общий тип, в большинстве случаев выбирается int. Во-вторых, char можно легко преобразовать в int (на самом деле, это действительно замаскированный short), но преобразование int в char не имеет большого смысла. Что за символ 123456? - person Vilx-; 29.02.2020
comment
@ Гарри, посмотри мой обновленный ответ. В этом разница между неявным и явным преобразованием. Тернарный оператор работает только с неявными преобразованиями. - person just.another.programmer; 29.02.2020
comment
Нет неявных преобразований из других типов в char, как указано здесь - person Pavel Anikhouski; 29.02.2020
comment
@PavelAnikhouski - именно это я упомянул в последнем абзаце своего ответа. - person just.another.programmer; 29.02.2020

Обратите внимание, что 'X' не string, это char. Числовое значение которого равно 88. Это числовое значение важно, потому что компилятор должен понимать эту операцию. :

true ? x : 0

В конечном итоге тернарная условная операция должна давать значение. Интуитивно понятно, что это значение может быть char или может быть int. Для компиляции кода это не может быть «может быть», он всегда должен быть одним из них. К счастью для компилятора, char можно напрямую преобразовать в int. В данном случае 88.

Таким образом, результатом операции является int, который выводится на консоль.

person David    schedule 29.02.2020

Это не тернарный оператор как таковой, это то, что символы могут быть неявно преобразованы в целые числа в C #, поэтому, столкнувшись со сценарием тернарного выражения, имеющего int и char и нуждающегося в «do if true» и «do if false» для быть последовательным, компилятор неявно преобразует char в int. ints не могут быть неявно преобразованы в символы, поэтому компилятор не пойдет по этому пути

int result = bool ? someChar : someInt; 

char result = bool ? (char)someInt : someChar;

Это оба в порядке; один использует неявное преобразование someChar в int для достижения согласованности (согласованного int) для тернарного элемента, другой использует явное приведение someInt в char для достижения согласованного char

Первый результат (печать, в вашем случае) int, второй приведет к char. Вы также можете поиграть с этим:

int result = bool ? (char)someInt : someChar;

Явное преобразование int в char, тернарное преобразование в char, неявное преобразование в int при сохранении в результате.

Код ascii для X - 88

person Caius Jard    schedule 29.02.2020