Как вычесть байты из одной строки в C#
Это действительно странно. Кто-нибудь может это объяснить?
Этот код не работает:
const byte ASC_OFFSET = 96;
string Upright = "firefly";
byte c7 = (byte)Upright[6] - ASC_OFFSET;
//Cannot implicitly convert type 'int' to 'byte'.
Этот код также не работает:
const byte ASC_OFFSET = 96;
string Upright = "firefly";
byte c7 = (byte)Upright[6] - (byte)ASC_OFFSET;
//Cannot implicitly convert type 'int' to 'byte'.
Тем не менее, наложение вычитания на отдельную строку работает просто отлично:
const byte ASC_OFFSET = 96;
string Upright = "firefly";
byte c7 = (byte)Upright[6];
c7 -= ASC_OFFSET;
Я не возражаю против того, чтобы поместить утверждения в отдельные строки, если это необходимо... но я должен задуматься...
Но почему?
3 ответа:
Я и раньше это замечал. Я думаю, это потому, что оператор
-=
предопределен для типов байтов, в то время как в предыдущих случаях вы действительно помещаетеint
внутрьbyte
, что недопустимо. Причина, по которой они это сделали, не обязательно имеет смысл, но она согласуется с правилами, потому что в предыдущих случаях компилятор не может "заглянуть" в оператор-
при выполнении задания.Если вам действительно нужно вычесть на одной строке, вместо того, чтобы говоря:
byte c7 = (byte)Upright[6] - ASC_OFFSET;
Скажи:
byte c7 = (byte)(Upright[6] - ASC_OFFSET);
Это потому, что 1)
byte
операции приводят кint
(см. Почему здесь: http://blogs.msdn.com/b/oldnewthing/archive/2004/03/10/87247.aspx ) и 2) следующий код C#c7 -= ASC_OFFSET;
Будет" волшебным образом " скомпилирован за сценой в
c7 = (byte)(c7 - ASC_OFFSET);
Это явно задокументировано в спецификации C# здесь: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
14.14.2 составное назначение:
Операция формы x op= y-это обрабатывается с применением бинарного оператора разрешение перегрузки (§14.2.4) как если бы операция была записана x op Y. Затем,
• Если возвращаемый тип выбранный оператор неявно преобразование к типу Х, операция оценивается как x = x op y, за исключением того, что x вычисляется только один раз.
• в противном случае, если выбранный оператор является предопределенным оператором, если возвращаемый тип выбранного оператора явно преобразуется в тип x, и если y неявно преобразуется в тип x или оператор является оператором сдвига, то операция вычисляется как x = (T) (x op y), где T-Тип x, за исключением того, что x вычисляется только один раз.
• В противном случае составное назначение является недопустимый и ошибка времени компиляции происходит
Причина, по которой ваши первые два образца не компилируются, заключается в следующем:
- приведение связывает "туже", чем вычитание. То есть "С)Д-Е "означает" С)Д-Е", а не "с) Д-Е". Оператор приведения имеет более высокий приоритет.
Поэтому тип обоих операндов для вычитания-байт, независимо от приведений.- тип вычитания-int, потому что нет оператора вычитания, определенного на байтах.
- Таким образом, вы присваиваете int байту без a актерский состав, что незаконно.
Нет никакого оператора вычитания на байтах, потому что, ну, предположим, у вас есть байт, содержащий 7, и вы вычитаете из него байт, содержащий 8, вы действительно хотите, чтобы это был байт 255? Я думаю, что большинство людей хотели бы, чтобы это было int -1.
Наконец, почему вы вообще делаете это в байтах? В этом нет никакого смысла. Символы не являются байтами в C#; если вы хотите делать арифметику на символах, то почему бы не вычесть char 96 из символа " y " вместо того, чтобы делать убыточное и опасное преобразование в байт?