Вопрос

На этот вопрос уже есть ответ здесь:

У меня есть этот код.

byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });

Когда я пытаюсь скомпилировать, я получаю:

Не может косвенно преобразовать тип «int» в байт '.Существует явное преобразование (вам не хватает актерского состава?)

Почему это происходит?Не должен | Два байта дают байт?Оба следующих варианта работают, гарантируя, что каждый элемент является байтом.

Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
Это было полезно?

Решение

Так задумано в C#, и фактически оно восходит к C/C++ — последний также переводит операнды в int, ты обычно этого не замечаешь, потому что int -> char преобразование там неявное, хотя в C# его нет.Это касается не только | либо, но для всех арифметических и побитовых операндов - например.добавление двух bytes даст вам int также.Я процитирую соответствующую часть спецификации здесь:

Бинарная числовая промоушена происходит для операндов предопределенного +, -, *, /, %, &, |, ^, ==,! =,>, <,> = И <= бинарных операторов.Бинарная числовая пропаганда неявно преобразует оба операнда в общий тип, который, в случае нереляционных операторов, также становится типом результата операции.Бинарная числовая пропаганда состоит из применения следующих правил, в том порядке, в котором они появляются здесь:

  • Если любой операнд имеет десятичное значение типа, другой операнд преобразуется в децимал типа, или возникает ошибка времени компиляции, если другой операнд имеет тип плавания или вдвое.

  • В противном случае, если любой операнд имеет двойной, другой операнд преобразуется в тип двойного.

  • В противном случае, если любой операнд имеет тип float, другой операнд преобразуется в Type Float.

  • В противном случае, если любой операнд имеет тип Ulong, другой операнд преобразуется в тип Ulong, или возникает ошибка времени компиляции, если другой операнд имеет тип Sbyte, Short, Int или Long.

  • В противном случае, если любой операнд имеет длинный тип, другой операнд преобразуется в тип длинного.

  • В противном случае, если один операнд имеет тип Uint, а другой операнд имеет тип Sbyte, Short или Int, оба операнда преобразуются в Long.

  • В противном случае, если любой операнд имеет тип Uint, другой операнд преобразуется в тип Uint.

  • В противном случае оба операнда преобразуются в тип Int.

Я не знаю точного обоснования этого, но могу подумать об одном.Особенно для арифметических операторов может быть немного удивительно получить (byte)200 + (byte)100 вдруг станет равным 44, даже если это имеет некоторый смысл, если внимательно рассмотреть задействованные типы.С другой стороны, int обычно считается типом, который «достаточно хорош» для арифметических вычислений с большинством типичных чисел, поэтому, повышая оба аргумента до int, в большинстве распространенных случаев вы получаете своего рода поведение «просто работает».

Что касается того, почему эта логика была также применена к побитовым операторам - я думаю, это в основном для обеспечения согласованности.В результате получается одно простое правило, общее для все нелогические двоичные типы.

Но это все в основном догадки.Эрик Липперт, вероятно, был бы тем, кто спросил бы о реальных мотивах этого решения, по крайней мере, для C# (хотя было бы немного скучно, если бы ответ был просто «так это делается в C/C++ и Java, и это достаточно хорошо». правило в его нынешнем виде, поэтому мы не видели причин его менять»).

Другие советы

Литерал 0x80 имеет тип «int», поэтому вы не обрабатываете байты.

То, что вы можете передать его в byte[], работает только потому, что 0x80 (как литерал) находится в диапазоне байтов.

Редактировать:Даже если 0x80 привести к байту, код все равно не скомпилируется, поскольку при операции oring байты все равно будут выдаваться int.Чтобы он скомпилировался, необходимо привести результат or: (byte)(0x80|dup)

byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });

Результатом побитового ИЛИ (|) для двух байтов всегда является целое число.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top