Question

    

Cette question a déjà une réponse ici:

    
            
  •              décalage gauche 255 (sous forme d'octet)                                      7 réponses                          
  •     
    

J'ai ce code.

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

Lorsque j'essaie de compiler, je reçois:

  

Impossible de convertir implicitement le type 'int'   à 'octet'. Une conversion explicite   existe (il vous manque un casting?)

Pourquoi cela se produit-il? Ne devrait pas | deux octets donnent un octet? Les deux travaux suivants garantissent que chaque élément est un octet.

Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
Était-ce utile?

La solution

C’est ce qui se fait de par la conception en C # et, en fait, remonte au C / C ++ - ce dernier promeut également les opérandes en int, vous ne vous en rendez pas compte, car int -> char la conversion effectuée implicite, alors que ce n'est pas en C #. Cela ne s'applique pas seulement à | non plus, mais à tous les opérandes arithmétiques et au niveau des bits - par exemple. ajouter deux byte vous donnera également un (byte)200 + (byte)100. Je citerai la partie pertinente de la spécification ici:

  

Une promotion numérique binaire survient pour   les opérandes du + prédéfini, & # 8211 ;,   *, /,%, & amp ;, |, ^, ==,! =, > ;, < ;, > = et < = opérateurs binaires . Binaire   promotion numérique convertit implicitement   les deux opérandes à un type commun qui,   en cas de non relationnel   opérateurs, devient également le résultat   type d'opération. Binaire numérique   La promotion consiste à appliquer le   règles suivantes, dans l’ordre dans lequel elles sont   apparaissent ici:

     
      
  • Si l'un des opérandes est de   tapez décimal, l'autre opérande est   converti en type décimal, ou un   erreur de compilation se produit si l'autre   l'opérande est de type float ou double.

  •   
  • Sinon, si l'un des opérandes est de   tapez double, l'autre opérande est   converti en type double.

  •   
  • Sinon,   si l'un des opérandes est de type float,   l'autre opérande est converti en type   float.

  •   
  • Sinon, si l'un des opérandes   est de type ulong, l'autre opérande est   converti en type ulong, ou un   erreur de compilation se produit si l'autre   l'opérande est de type sbyte, short, int,   ou long.

  •   
  • Sinon, si soit   l'opérande est de type long, l'autre   l'opérande est converti en type long.

  •   
  • Sinon, si l'un des opérandes est de   tapez uint et l'autre opérande est de   tapez sbyte, short ou int, les deux   les opérandes sont convertis en type long.

  •   
  • Sinon, si l'un des opérandes est de   tapez uint, l'autre opérande est   converti en type uint.

  •   
  • Sinon,   les deux opérandes sont convertis en type   int.

  •   

Je ne connais pas la raison exacte de cela, mais je peux en penser à un. Pour les opérateurs arithmétiques en particulier, il peut être un peu surprenant que les gens obtiennent 44 tout à coup l’équivalent de <=>, même si cela a du sens de considérer avec soin les types impliqués. Par contre, <=> est généralement considéré comme un type & "Suffisant" & "; pour l'arithmétique sur la plupart des nombres typiques, donc en promouvant les deux arguments en <=>, vous obtenez une sorte de & "tout fonctionne" & "; comportement dans les cas les plus courants.

Quant à savoir pourquoi cette logique a également été appliquée aux opérateurs au niveau des bits - j’imagine que c’est surtout pour des raisons de cohérence. Il en résulte une seule règle simple commune à tous les types binaires non booléens.

Mais tout cela est plutôt difficile à deviner. Eric Lippert serait probablement celui qui poserait au moins les raisons qui ont motivé cette décision pour C # (bien que ce serait un peu ennuyeux si la réponse est simplement & "C'est comme ça que ça se passe en C / C ++ et en Java, et c’est une règle assez bonne, alors nous n’avons vu aucune raison de la changer ").

Autres conseils

Le littéral 0x80 a le type " int " ;, de sorte que vous n'utilisez pas d'octets.

Le fait que vous puissiez le transmettre à l'octet [] ne fonctionne que parce que 0x80 (littéralement) se situe dans la plage d'octet.

Modifier : même si 0x80 est converti en octet, le code ne sera toujours pas compilé, car les octets oring donneront toujours int. Pour le compiler, le résultat de ou doit être converti: (byte)(0x80|dup)

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

Le résultat d'un bit au niveau des bits Ou (|) sur deux octets est toujours un entier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top