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

Почему "привет" + + '/' + "world" == "hello47world"?

Для этого С#, a==true:

bool a = "hello" +   '/' + "world" == "hello/world";

И для этого С#, b==true:

bool b = "hello" + + '/' + "world" == "hello47world";

Мне интересно, как это может быть и что еще более важно, почему архитекторы языка С# выбрали это поведение?

4b9b3361

Ответ 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.