2009-10-01 2 views
31

У меня вопрос о неявном преобразовании типаНеявный тип, отлитый в C#

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

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

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

Это действительно хороший вопрос. В C символ более или менее является синонимом байта, они оба являются числовыми типами. В C#, однако, символ является символом unicode ... –

+0

, поэтому ответ будет заключаться в том, что символ является символом Unicode, поэтому он работает на C#? – tintincutes

+20

Как раз для того, чтобы исправить ваше использование жаргона - это не подразумеваемый литой. Это неявное преобразование. «Кастинг» - это использование оператора трансляции; неявное преобразование - это преобразование, которое НЕ требует оператора трансляции. –

ответ

2

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

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

0

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

+2

Хотя это правдоподобно, это рассуждение на самом деле не логично. Если бы это было рассуждение, тогда было бы неявное преобразование из ushort в char, но такого неявного преобразования нет. –

12

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

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

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

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

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

+3

Итак, что объясняет, почему в C# нет неявного преобразования из короткой ссылки на char? Это можно сделать без потерь; ваша логика укажет, что должно быть неявное преобразование от short к char, но нет. Почему нет? –

+0

Вот почему я сказал «базовую идею», так как получил ее из книги «CLR через C#». Последнее слово сказано в ссылке, как цитирует _Dzmitry Huba_. Я не знаю об обосновании этого решения, но я ожидаю, что они попытались немного улучшить семантическую разницу между символами и цифрами, подобно тому, как нужно пометить параметры 'ref' и' out' на сайте call-сайта. – gimpf

+0

Действительно. Как оказалось, я немного разбираюсь в обосновании этого решения.Твоя гипотеза на месте. :) –

0

Символ неявно отображается в его числовом значении Unicode, которое является целым числом.

+2

Тип 'char' представляет символы Unicode. Только 128 из 65 536 возможных значений «char» имеют эквивалент ASCII. – LukeH

+0

Вы правы, я не уверен, что я там думал ... отредактировал. –

9

От C# Спецификация

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

• От SByte к короткому, междам, длинные, поплавка, двойным или десятичной системе.

• От байта до короткого, ushort, int, uint, long, ulong, float, double, или decimal.

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

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

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

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

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

• От ulong до float, double, или decimal.

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

• От поплавка до двойного.

Конверсии междунар, UINT, длинные или ULONG плавать и с длинными или ULong вдвое может привести к потере точности, но никогда не приведет к потере величины. Другие неявные числовые преобразования никогда не теряют никакой информации . Нет никаких неявных преобразований в тип char, поэтому значения других интегральных типов do не автоматически преобразуются в char .

3

На странице MSDN о полукоксе (char (C# Reference):.

полукокс может быть неявно преобразован в UShort, INT, UINT, длинный, ULONG, поплавок, двойник, или десятичный Однако, есть нет неявного преобразования из других типов к типу CHAR.

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

+0

да, поэтому я также задавался вопросом, я новичок в программировании, но, как объясняет мой учитель, я видел несоответствие этого. Особенно в C#, они очень строги к правилам OO, и они должны быть чистыми все время, и это довольно удивительно. – tintincutes

+0

'char' не * явно * реализует «неявное литье». Если вы посмотрите на источник Char с отражателем, вы не увидите ни одного из них. Некоторые ** конверсии ** неявно относятся к самому языку. –

70

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+0

+ Какой символ бесконечности? Также это был отличный пост в блоге. – Kredns

+0

Было бы неплохо (иногда), если бы это работало из коробки на C#, хотя, как и в C: for (char letter = 'A'; letter <= 'Z'; letter + = 2) –

+1

Для запись выше, работает в C#, с немного большим синтаксисом: letter = (char) (letter + 2) –

0

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

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

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

Смежные вопросы