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

Неявный приведение типа char к int в С#

У меня есть вопрос о неявном преобразовании типа

Почему это неявное преобразование типов работает на С#? Я узнал, что неявный код обычно не работает.

У меня есть пример кода здесь о неявном преобразовании типа

 char c = 'a';
 int x = c;
 int n = 5;
 int answer = n * c;
 Console.WriteLine(answer);
4b9b3361

Ответ 1

Литье приведет к потере данных. Здесь char - 16 бит и int 32 бит. Таким образом, передача будет происходить без потери данных.

Пример реальной жизни: мы можем поместить небольшое судно в большой сосуд, но не наоборот, без внешней помощи.

Ответ 2

ОБНОВЛЕНИЕ: Я использую этот вопрос в качестве темы моего блога сегодня. Спасибо за большой вопрос. Пожалуйста, см. Блог для будущих дополнений, обновлений, комментариев и т.д.

http://blogs.msdn.com/ericlippert/archive/2009/10/01/why-does-char-convert-implicitly-to-ushort-but-not-vice-versa.aspx


Мне не совсем понятно, что именно вы спрашиваете. "Почему" вопросы трудно ответить. Но я сделаю снимок.

Сначала код, который имеет неявное преобразование из char в int (обратите внимание: это не "неявный перевод", это "неявное преобразование" ) является законным, поскольку спецификация С# четко заявляет, что существует неявное преобразование из char в int, и в этом отношении компилятор корректно реализует спецификацию.

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

Ну, во-первых, очевидные вещи, которые помешали бы этому быть правилом языка, не применяются. A char реализуется как неподписанное 16-битное целое число, которое представляет символ в кодировке UTF-16, поэтому его можно преобразовать в ushort без потери точности или, если на то пошло, без изменения представления. Время выполнения просто переходит от обработки этого битового шаблона как char к обработке одного и того же битового шаблона в виде пользовательского ввода.

Таким образом, можно разрешить преобразование из char в ushort. Теперь, только потому, что что-то возможно, это не значит, что это хорошая идея. Понятно, что разработчики языка думали, что неявное преобразование char в ushort было хорошей идеей, но неявно преобразование ushort в char не является. (И поскольку char для ushort - хорошая идея, кажется разумным, что char -to-anything-that-ushort-go-to также разумно, следовательно, char для int. Кроме того, я надеюсь, что это понятно, почему разумное литье ushort в char разумно, ваш вопрос касается неявных преобразований.)

Итак, у нас на самом деле есть два связанных вопроса: во-первых, почему это плохая идея разрешить неявные преобразования из ushort/short/byte/sbyte в char? и, во-вторых, почему это хорошая идея разрешить неявные преобразования из char в ushort?

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

Первый вопрос рассмотрен в примечаниях от 14 апреля 1999 года, где возникает вопрос о том, должно ли оно быть законным для преобразования из байта в char. В исходной предварительной версии С# это было законным в течение короткого времени. Я слегка отредактировал заметки, чтобы сделать их понятными без понимания предварительных выпусков Microsoft-кодов 1999 года. Я также добавил акцент на важные моменты:

[Комитет по разработке языков] решил предоставить неявное преобразование из байтов в символов, так как домен одного из них полностью содержащихся в другом. Однако сейчас [время выполнения библиотека] предоставляют только методы Write которые принимают символы и ints, что означает что байты печатаются как символы так как это становится лучшим метод. Мы можем решить это предоставление большего количества методов в Writer класса или путем удаления неявного преобразование.

Существует аргумент в пользу того, почему последнее - правильная вещь. В конце концов, байты действительно не символы. Правда, может быть полезное отображение от байтов до символов, но в конечном счете 23 не обозначает то же самое, что и персонаж с ascii значение 23, таким же образом, что 23B означает то же, что и 23L. Запрашиваемая [авторов библиотеки], чтобы предоставить дополнительный метод просто из-за как причуда в нашей системе типов работает кажется довольно слабым. Поэтому я бы предположим, что мы делаем преобразование от байта до char явного.

В заключение следует, что байт-to- char должен быть явным преобразованием, а integer-literal-in-range-of-char также должен быть явным преобразованием.

Обратите внимание, что примечания о дизайне языка не вызывают, почему ushort-to- char также были незаконными одновременно, но вы можете видеть, что применяется та же логика. Когда вы вызываете метод, перегруженный как M (int) и M (char), когда вы передаете его в ushort, вероятность хорошая, что вы хотите рассматривать ushort как число, а не как символ. И ushort НЕ является символьным представлением таким же образом, что ushort является числовым представлением, поэтому представляется разумным сделать это преобразование незаконным, а также.

Решение о том, чтобы сделать char перейти к ushort было сделано 17 сентября 1999 года; в примечаниях к дизайну с этого дня на эту тему просто указывается, что "char для ushort также является юридическим неявным преобразованием", и что он. Никакое дальнейшее изложение того, что происходило в главах разработчиков языков, в тот день не видно в заметках.

Однако мы можем сделать обоснованные догадки о том, почему неявный char -to-ushort считается хорошей идеей. Ключевая идея здесь заключается в том, что преобразование из числа в символ является "возможно хитроумным" преобразованием. Это принятие чего-то, что вы не знаете, предназначено быть персонажем и выбирает рассматривать его как одно. Это похоже на то, что вы хотите назвать, что вы делаете явно, а не случайно позволяете это. Но обратное гораздо менее изворотливое. В C-программировании существует долгая традиция обработки символов как целых чисел - для получения их базовых значений или для их математики.

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

Отвечает ли это на ваш вопрос?

Ответ 3

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

Таким образом, неявное преобразование из char в int будет работать на С#.

[edit] Как указывали другие, char - это 16-разрядное число в С#, поэтому это преобразование происходит только с 16-разрядного целого числа до 32-разрядного целого числа, что возможно без потери данных. [/править]

С# поддерживает неявные преобразования, часть "обычно не работает", вероятно, исходит из какого-то другого языка, возможно, С++, где некоторые славные реализации string обеспечивали неявные преобразования для разных типов указателей, создавая некоторые гигантские ошибки в приложениях.

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

Ответ 4

Из спецификации С#

6.1.2 Неявные числовые преобразования Неявные числовые преобразования:

• От sbyte до short, int, long, float, double или decimal.

• От байта до короткого, ushort, int, uint, long, ulong, float, double или десятичная дробь.

• От short до int, long, float, двойной или десятичный.

• От ushort до int, uint, long, ulong, float, double или decimal.

• От int до long, float, double или десятичная дробь.

• От uint до long, ulong, float, двойной или десятичный.

• От длинного до плавающего, двойного или десятичная дробь.

• От ulong до float, double или десятичная дробь.

• Из char в ushort, int, uint, long, ulong, float, double или десятичная дробь.

• От float до double.

Преобразования из int, uint, long или улонг плавать и длинные или улунговые удвоить может привести к потере точность, но никогда не приведет к потере. Другой неявный числовые преобразования никогда не теряют Информация. Нет никаких подразумеваемых преобразования в тип char, поэтому значения других интегральных типов не автоматически конвертировать в charтип.

Ответ 5

На странице MSDN о char (char (ссылка на С#):

A char может быть неявно преобразован в ushort, int, uint, long, ulong, float, double или decimal. Однако нет никаких неявных преобразований из других типов в тип char.

Это потому, что они применили неявный метод от char ко всем этим типам. Теперь, если вы спросите, почему они их реализовали, я действительно не уверен, конечно, чтобы помочь работать с ASCII-представлением символов или что-то в этом роде.

Ответ 6

Ядром записи в блоге @Eric Lippert является его обоснованное предположение о причинах такого решения разработчиков языка С#:

"There is a long tradition in C programming of treating characters as integers 
-- to obtain their underlying values, or to do mathematics on them."

Это может вызвать ошибки, такие как:

var s = new StringBuilder('a');

Как вы думаете, инициализация StringBuilder инициализируется символом "a", но фактически устанавливает емкость StringBuilder равной 97.

Ответ 7

Это работает, потому что каждый символ обрабатывается внутри как число, поэтому приведение неявно.

Ответ 8

char неявно приводится к нему числовое значение Unicode, которое является целым числом.

Ответ 9

Преобразование имплицита из char в числовые типы не имеет смысла, на мой взгляд, потому что происходит потеря информации. Вы можете увидеть это в этом примере:

string ab = "ab";
char a = ab[0];
char b = ab[1];
var d = a + b;   //195

Мы поместили все фрагменты информации из строки в символы. Если по какой-либо причине сохраняется только информация из d, все, что осталось нам, - это номер, который не имеет смысла в этом контексте и не может использоваться для восстановления ранее предоставленной информации. Таким образом, наиболее полезным способом было бы неявно преобразовать "сумму" символов в строку.