Почему "привет" + + '/' + "world" == "hello47world"?
Для этого С#, a==true
:
bool a = "hello" + '/' + "world" == "hello/world";
И для этого С#, b==true
:
bool b = "hello" + + '/' + "world" == "hello47world";
Мне интересно, как это может быть и что еще более важно, почему архитекторы языка С# выбрали это поведение?
Ответы
Ответ 1
Второй +
преобразует char
в int
и добавляет его в строку. Значение ASCII для /
равно 47, которое затем преобразуется в строку другим оператором +.
Оператор +
перед косой чертой неявно передает его в int. См. + Operator в MSDN и посмотрите на "унарный плюс".
Результат операции унарного + для числового типа - это просто значение операнда.
Я действительно понял это, посмотрев, что на самом деле звонили операторы +
. (Я думаю, что это функция ReSharper или VS 2015)
![введите описание изображения здесь]()
![введите описание изображения здесь]()
Ответ 2
Это потому, что вы используете унарный оператор +
. Он похож на унарный оператор -
, но он не меняет знак операнда, поэтому единственный эффект, который он имеет здесь, заключается в неявном преобразовании символа '/'
в int
.
Значение +'/'
- это код символа /
, который равен 47.
Код делает то же самое, что:
bool b = "hello" + (int)'/' + "world" == "hello47world";
Ответ 3
Почему, я слышал, вы спрашиваете, есть ли char
, специально обработанный оператором int operator +(int x)
, а не один из многих других доступных унарных +
операторов? > :
- унарные правила разрешения перегрузки оператора говорят сначала, чтобы посмотреть на пользовательские унарные операторы, но поскольку
char
не имеет ни одного из них, компилятор выглядит на предопределенных унарных операторах +
.
- Очевидно, что ни один из них не принимает
char
, поэтому компилятор использует правила разрешения перегрузки чтобы решить, какой оператор (int
, uint
, long
, ulong
, float
, double
decimal
) является лучшим.
- В этих правилах разрешения говорится, что это лучшая функция... в значительной степени говорит, что тип аргумента предлагает лучшее преобразование от
char
.
-
int
превосходит long
, float
и double
, потому что вы можете неявно конвертировать int
в эти типы и не вернуться.
-
int
бьет uint
и ulong
, потому что... лучшее правило преобразования говорит, что оно делает.
Ответ 4
Как это происходит, это неявный листинг ( "A char может быть неявно преобразован в ushort, int, uint, long, ulong, float, double или decimal". (char MSDN).
Самая простая форма воспроизведения может быть найдена как
int slash = +'/'; // 47
Char внутренне является структурой. "Назначение: это класс значений, представляющий символ Unicode" (char.cs ms sourcesource), и причина, по которой структура может быть неявно использована, заключается в том, что она реализует интерфейс IConvertible.
public struct Char : IComparable, IConvertible
В частности, с помощью этого фрагмента кода
/// <internalonly/>
int IConvertible.ToInt32(IFormatProvider provider) {
return Convert.ToInt32(m_value);
}
Интерфейс IConvertible
указывает в комментарии в коде
//Интерфейс IConvertible представляет объект, который содержит значение. Это
//интерфейс реализуется следующими типами в пространстве имен System:
//Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64,
//Single, Double, Decimal, DateTime, TimeSpan и String.
Оглядываясь на цель структуры (чтобы быть значением, представляющим символ юникода), ясно, что намерение этого поведения на языке было обеспечить способ преобразования значения в поддерживаемые типы. IConvertible
переходит в состояние
//Реализации IConvertible, предоставляемые классами значений System.XXX
//просто переходим к соответствующим методам Value.ToXXX(YYY) (описание файла // класс Value следует ниже). В тех случаях, когда метод Value.ToXXX(YYY)
//не существует (поскольку конкретное преобразование не поддерживается), // Реализация IConvertible должна просто вызывать InvalidCastException.
В явном виде указано, что преобразования, которые не поддерживаются, исключают исключения. Также явно указано, что преобразование символа в целое число даст целочисленное значение этого символа.
Метод ToInt32 (Char) возвращает 32-разрядное целое число со знаком, которое представляет кодированный код кода UTF-16 аргумента значения. Метод Convert.ToInt32 (Char) MSDN
В целом, рассуждения о поведении кажутся очевидными. Целочисленное значение char имеет смысл как "кодированный код кода UTF-16". Значение обратной косой черты - 47.
В результате приведенного значения значения и поскольку char
является встроенным числовым типом, неявное преобразование в целое число из знака плюс выполняется во время компиляции. Это можно увидеть при повторном использовании приведенного выше простого примера в небольшой программе (linqpad работает, чтобы проверить это)
void Main()
{
int slash = +'/';
Console.WriteLine(slash);
}
становится
IL_0000: ldc.i4.s 2F
IL_0002: stloc.0 // slash2
IL_0003: ldloc.0 // slash2
IL_0004: call System.Console.WriteLine
IL_0009: ret
Если '/'
просто преобразуется в шестнадцатеричное значение 2F (47 в десятичной форме), а затем используется оттуда.
Ответ 5
+ '/'
Дает вам код символа UTF-16 (decimal) 47
символа "/", а @Guffa уже объяснил вам, почему.
Ответ 6
Как и в С# a char выражается в одинарных кавычках, т.е. "/" в вашем случае, оператор + перед char действует как унарный оператор и просит компилятор предоставить значение UTF для char '/', который равен 47.