Pergunta

Esta questão já tem uma resposta aqui:

Eu tenho esse código.

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

Quando tento compilar recebo:

Não é possível converter implicitamente tipo 'int' para 'byte'. Uma conversão explícita existe (faltam um elenco?)

Por que isso acontece? não deve | dois bytes dar um byte? Ambos os seguintes trabalhos, garantindo que cada item é um byte.

Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
Foi útil?

Solução

É dessa maneira por design em C #, e, de fato, remonta todo o caminho para C / C ++ - este último também promove operandos para int, você só geralmente não percebe porque a conversão int -> char há implícita, embora seja não em C #. Isto não se aplica apenas para | qualquer um, mas a todos os operandos aritméticos e bit a bit - por exemplo, adicionando duas bytes lhe dará uma int também. Vou citar a parte relevante da especificação aqui:

Binary promoção numérico ocorre para operandos do predefinidos +, -, *, /,%, &, |, ^, ==, =,>, <,> =, e <= operadores binários!. Binário promoção numérico converte implicitamente ambos os operandos para um tipo comum que, no caso do não-relacional operadores, também se torna o resultado tipo de operação. numérico binário promoção consiste em aplicar a seguindo as regras, na ordem em que apareça aqui:

  • Se qualquer operando é do tipo decimal, o outro operando é convertido para o tipo decimal, ou um erro de compilação ocorre se o outro operando é do tipo float ou double.

  • Caso contrário, se o operando é de tipo duplo, o outro é operando convertido para o tipo duplo.

  • Caso contrário, se quer operando é do tipo flutuador, o outro operando é convertido no tipo float.

  • Caso contrário, se o operando é do tipo ulong, o outro operando é convertido para o tipo ulong, ou um erro de compilação ocorre se o outro operando é do tipo sbyte, short, int, ou longo prazo.

  • Caso contrário, se quer operando é do tipo de comprimento, a outra operando é convertido no tipo longa.

  • Caso contrário, se o operando é de tipo uint e o outro operando é de Tipo sbyte, short ou int, tanto operandos são convertidos para o tipo long.

  • Caso contrário, se o operando é de tipo uint, o outro operando é convertidos para o tipo uint.

  • Caso contrário, ambos os operandos são convertidos para o tipo int.

Eu não sei a razão exata para isso, mas eu posso pensar em um. Para os operadores aritméticos especialmente, pode ser um pouco surpreendente para as pessoas obterem (byte)200 + (byte)100 repente igual a 44, mesmo que isso faz algum sentido quando se considera cuidadosamente os tipos envolvidos. Por outro lado, int é geralmente considerado um tipo que é "bom o suficiente" para aritmética sobre a maioria dos números típicos, assim, promovendo ambos os argumentos para int, você começa uma espécie de "simplesmente funciona" comportamento para a maioria dos casos comuns.

Quanto ao porquê esta lógica também foi aplicada a bit a bit operadores - Eu imagino que isso é assim na maior parte para a consistência. Isso resulta em uma única regra simples que é comum para todas tipos binários não-booleanas.

Mas tudo isso é principalmente adivinhando. Eric Lippert provavelmente seria o único a perguntar sobre os reais motivos por trás desta decisão para C #, pelo menos, (apesar de que seria um pouco chato se a resposta é simplesmente "é como ele é feito em C / C ++ e Java, e é uma boa o suficiente norma, tal como é, por isso, não viu nenhuma razão para mudá-lo ").

Outras dicas

O 0x80 literal tem a "int" tipo, para que não sejam oring bytes.

Que você pode passá-lo para o byte [] só funciona porque 0x80 (como um literal) está dentro do intervalo de byte.

Editar : Mesmo se 0x80 é convertido para um byte, o código ainda não compilar, desde ORING bytes vai ainda dar int. Para tê-lo compilar, o resultado da ou deve ser lançado: (byte)(0x80|dup)

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

O resultado de uma operação OR (|). Em dois bytes é sempre um int

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top