Как вычесть байты из одной строки в 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 4

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 " вместо того, чтобы делать убыточное и опасное преобразование в байт?