Неявное преобразование из char в односимвольную строку - PullRequest
0 голосов
/ 11 сентября 2018

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

Сегодня я столкнулся с небольшой, но влиятельной ошибкой в ​​нашей кодовой базе, где константа intбыл инициализирован представлением char того же числа.Это приводит к ASCII преобразованию char в int.Примерно так:

char a = 'a';
int z = a;
Console.WriteLine(z);    
// Result: 97

Я был озадачен, почему C # допускает что-то подобное.Обыскав вокруг, я нашел следующий SO вопрос с ответом самого Эрика Липперта: Неявный приведение типа в C #

Выдержка:

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

Я могу согласиться с обоснованием этого, хотя подсказка IDEбыло бы здорово.Однако у меня есть другая ситуация, когда неявное преобразование внезапно становится не законным:

char a = 'a';
string z = a; // CS0029 Cannot implicitly convert type 'char' to 'string'

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

Так что это подводит меня к моему актуальному вопросу:

Какие могут быть причины у команды разработчиков C #, чтобы не реализовывать неявное преобразование из char в string, в то время как это выглядит настолько очевидным по внешнему виду (особенно при сравнении с *Преобразование 1034 * в int).

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Char является типом значения.Нет, он не является числовым, как int или удваивается, но все еще происходит от System.ValueType.Тогда переменная char живет в стеке.

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

0 голосов
/ 11 сентября 2018

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

Но я не хочу просто отвергать посылку из-под контроля;вопрос может быть лучше сформулирован как «каковы плюсы и минусы данной предлагаемой функции?»

Это вполне разумная функция, и есть языки, которые позволяют вам рассматривать отдельные символы как строки.(Тим упомянул VB в комментарии, и Python также рассматривает символы и односимвольные строки как взаимозаменяемые IIRC. Я уверен, что есть и другие.) Однако, если бы я представил эту функцию, я бы указал на несколько недостатков:

  • Это новая форма конверсии бокса.Символы - дешевые типы стоимости.Строки являются выделенными в куче ссылочными типами.Конверсионные преобразования могут вызывать проблемы с производительностью и вызывать давление при сборе, поэтому необходимо привести аргумент, что они должны быть более заметными в программе, а не менее заметными.
  • Эта функция не будет восприниматься как "символы, которые можно преобразовать в односимвольные строки".Это будет восприниматься пользователями как "символы являются односимвольными строками", и теперь совершенно разумно задавать множество дополнительных вопросов, например: можно ли назвать .Length на символе?Если я могу передать символ в метод, который ожидает string, и я могу передать строку в метод, который ожидает IEnumerable<char>, могу ли я передать char в метод, который ожидает IEnumerable<char>?Это кажется ... странным.Я могу вызвать Select и Where в строке;можно на чарсе?Это кажется еще более странным.Все, что предлагается, это переместить ваш вопрос ;Если бы это было реализовано, вы бы теперь спросили: «Почему я не могу позвонить в Select на символе?»или что-то подобное.

  • Теперь объедините два предыдущих пункта вместе.Если я думаю о символах как об односимвольных строках и преобразую символ в объект, получу ли я в штучной упаковке символ или строку?

  • Мы также можем обобщить вторую точку немного дальше.Строка представляет собой набор символов.Если мы собираемся сказать, что символ может быть преобразован в коллекцию символов, зачем останавливаться на строках?Почему бы не сказать, что символ также может быть использован как List<char>?Зачем останавливаться на char?Должны ли мы сказать, что int конвертируется в IEnumerable<int>?
  • Мы можем обобщить еще больше: если есть очевидное преобразование из char в последовательность последовательность символов в строке, то также есть очевидное преобразование из char в Task<char> - просто создайтезавершенная задача, которая возвращает символ - и Func<char> - просто создайте лямбду, которая возвращает символ - и Lazy<char>, и Nullable<char> - о, подождите, мы делаем разрешить преобразование в Nullable<char>.: -)

Все эти проблемы решаемы, и некоторые языки их решили.Это не проблема.Проблема в том, что все эти проблемы проблем, которые команда разработчиков языка должна определить, обсудить и решить .Одной из фундаментальных проблем в дизайне языка является насколько общей должна быть эта функция? За две минуты я перешел от слова "символы, преобразуемые в односимвольные строки", к "любому значению базового типа, которое можно преобразовать".к эквивалентному значению монадического типа ".Есть аргумент, который необходимо сделать как для особенностей, так и для различных других точек спектра общности.Если вы сделаете свой язык слишком специфичным, это станет массой особых случаев, которые плохо взаимодействуют друг с другом.Если вы сделаете их слишком общими, я думаю, у вас есть Haskell.: -)

Предположим, что команда разработчиков пришла к выводу об этой функции: все это должно быть написано в проектной документации и спецификации, а также должны быть написаны код и тесты, и, о, я упоминал, чтокаждый раз, когда вы вносите изменения в правила конвертируемости, кто-то нарушает код разрешения перегрузки?Правила конвертируемости вы действительно должны получить правильно в первой версии, потому что изменение их позже делает существующий код более хрупким.Существуют реальные затраты на проектирование и реальные затраты для реальных пользователей, если вы сделаете такого рода изменения в версии 8 вместо версии 1.

Теперь сравните эти недостатки - и я уверен, что есть и другиеЯ не перечислил - на верх.Достоинства довольно крошечные: вы избегаете одного вызова ToString или + "" или чего бы то ни было, чтобы явно преобразовать символ в строку.

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

Как я уже сказал, это разумная функция, и она былабыл бы в версии 1 языка - который не имел ни дженериков, ни установленной базы в миллиарды строк кода - тогда было бы гораздо проще продать.Но теперь, есть много функций, которые имеют больший удар для меньшего доллара.

0 голосов
/ 11 сентября 2018

Потому что, когда вы выполняете приведение от char к int, вы не просто меняете его тип, вы получаете его индекс в таблице ASCII, что на самом деле отличается, они не позволяют вы «конвертируете char в int», они дают вам полезные данные для возможной необходимости.

Почему бы не разрешить разыграть от char до string?

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

Символ и строка не являются двумя способами выражения одного и того же.

...