C# XOR sur deux variables byte ne compilera pas sans cast [dupliquer]

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

pourquoi ce qui suit génère une erreur de temps de compilation: "ne peut pas convertir implicitement le type "int" en "byte":

        byte a = 25;
        byte b = 60;

        byte c = a ^ b;

cela aurait du sens si j'utilisais un opérateur arithmétique parce que le résultat de a + b pourrait être plus grand que peut être stocké dans un seul octet.

cependant appliquer ceci à l'opérateur XOR est inutile. XOR ici il une opération bitwise qui ne peut jamais déborder un octet.

utilisant un moulage autour des deux opérandes œuvres:

byte c = (byte)(a ^ b);
27
demandé sur Ash 2010-04-28 08:57:09

8 réponses

Je ne peux pas vous donner la raison, mais je peux dire pourquoi le compilateur a ce comportement du point de vue des règles que le compilateur doit suivre (ce qui pourrait ne pas être vraiment ce que vous êtes intéressant à savoir).

D'une ancienne copie de la c # spec( je devrais probablement télécharger une nouvelle version), emphasis added:

14.2.6.2 promotions numériques binaires cette clause est informative.

binaire la promotion numérique se produit pour les opérandes des prédéfinis + , ? , * , / , % , & , | , ^ , == , != , > , < , >= , et <= opérateurs binaires. Binaire conversion implicite de la promotion numérique les deux opérandes à un type commun qui, dans le cas du non-relationnel opérateurs, devient aussi le résultat type de l'opération. Binaire numérique la promotion consiste à appliquer les règles suivantes, dans l'ordre qu'ils

  • si l'un des opérandes est de type décimal, l'autre opérande est converti en type décimal, ou a erreur de compilation se produit si l'autre operand est de type float ou double.
  • Sinon, si l'un des opérandes est de type double, l'autre opérande est converti en type double.
  • autrement, si l'un ou l'autre des opérandes est de type float, l'autre opérande est converti en type flottant.
  • Sinon, si l'un des opérandes est de type ulong, l'autre opérande est converti en ulong de type, ou un erreur de compilation se produit si l'autre l'opérande est de type sbyte, short, int, ou long.
  • Sinon, si l'un des opérandes est de type long, l'autre opérande est converti en type long.
  • dans les autres cas, si l'une ou l'autre des opérandes est de type uint et que la autre opérande est de type sbyte, court, ou int, les deux les opérandes sont converties en type long.
  • Sinon, si l'un des opérandes est de type uint, l'autre opérande est converti en uint de type.
  • sinon, les deux opérandes sont converties en type int .

donc, essentiellement des opérandes plus petites qu'un int seront converties en int pour ces opérateurs (et le résultat sera un int pour les ops non relationnelles).

j'ai dit que je ne pouvais pas vous donner une raison; cependant, je vais faire une conjecture à un - je pense que les concepteurs de C# ont voulu s'assurer que les opérations qui pourraient perdre de l'information Si rétrécie devrait avoir cette opération de rétrécissement Rendu explicite par le programmeur sous la forme d'un plâtre. Par exemple:

byte a = 200;
byte b = 100;

byte c = a + b;  // value would be truncated

alors que ce genre de troncature ne se produirait pas lors de l'exécution d'une opération xor entre deux opérandes byte, je pense que les concepteurs du langage ne voulaient probablement pas d'un ensemble plus complexe de règles où certaines opérations auraient besoin de moulages explicites et d'autres pas.


juste une petite note: la citation ci-dessus est "informative" pas "normative", mais il couvre tous les cas dans une forme facile à lire. Strictement parlant (au sens normatif), la raison pour laquelle l'opérateur ^ se comporte de cette manière est parce que la surcharge la plus proche pour cet opérateur dans le cadre des opérandes byte est (à partir de 14.10.1 "opérateurs logiques entiers"):

int operator ^(int x, int y); 

par conséquent, comme l'explique le texte informatif, les opérandes sont promues à int et un résultat int est produit.

22
répondu Michael Burr 2010-04-28 07:02:27

le programmeur demigod de Microsoft a une réponse: http://blogs.msdn.com/oldnewthing/archive/2004/03/10/87247.aspx

et peut-être que c'est plus sur la conception des compilateurs. Ils rendent le compilateur plus simple en généralisant le processus de compilation, il n'a pas à regarder l'opérateur des opérandes, donc il a regroupé les opérations bitwise dans la même catégorie que les opérateurs arithmétiques. Ainsi, soumis au type élargissement

2
répondu Michael Buen 2010-04-28 05:16:40

je suppose que c'est parce que L'opérateur XOR est défini pour les booléens et les entiers.

et un cast du résultat du résultat entier à un octet est une conversion de perte d'information ; nécessite donc un cast explicite (nod du programmeur).

1
répondu Gishu 2010-04-28 05:04:36

cela a plus à voir avec les règles entourant la coulée implicite et explicite dans la spécification CLI. Un entier (int = système.Int32 = 4 octets) est plus large qu'un octet (1 octet, évidemment!). Par conséquent, tout moulage de l'int à l'octet est potentiellement un moulage rétrécissant. Par conséquent, le compilateur veut vous faire explicitement.

0
répondu James Webster 2010-04-28 05:04:45

je pensais que je me souvenais d'une question populaire à ce sujet.

octet + octet = int... pourquoi?

0
répondu Spencer Ruport 2017-05-23 10:30:59

il semble que c'est parce que dans les spécifications de langage C#, il est défini pour entier et long http://msdn.microsoft.com/en-us/library/aa691307%28v=VS.71%29.aspx

ainsi, ce qui se passe réellement est que le compilateur projette des opérandes byte à int implicitement parce qu'il n'y a pas de perte de données de cette façon. Mais le résultat (qui est int) ne peut pas être dévalorisé sans perte de données (implicitement). Donc, vous devez dire explicitement au compilateur que vous savez ce que vous faites!

0
répondu Omer Akhter 2010-04-28 05:37:54

pourquoi les deux octets doivent être converties en ints pour faire le XOR?

si vous voulez creuser dedans, 12.1.2 de la CLI Spec (Partition I) décrit le fait que, sur la pile d'évaluation, seulement int ou long peut exister. Tous les types intégraux plus courts doivent être élargis pendant l'évaluation.

malheureusement, je ne peux pas trouver un lien approprié directement à la spécification CLI - j'ai une copie locale en PDF, mais je ne me souviens pas d'où je l'ai obtenu.

0
répondu Damien_The_Unbeliever 2010-04-28 07:27:54

FWIW octet a = 25; octet B = 60; a = A ^ b; ne fonctionne pas. Cependant octet a = 25; octet B = 60; a ^= b; n'travail.

-1
répondu Dan Honeycutt 2016-10-20 03:59:46