2010-09-04 13 views

risposta

29

Sorprendentemente, quando si eseguono operazioni su byte, i calcoli verranno eseguiti utilizzando i valori int, con i byte convertiti implicitamente su (int). Questo vale anche per short s e allo stesso modo float s vengono convertiti in up to double quando si esegue l'aritmetica in virgola mobile.

Il secondo frammento è equivalente a:

byte someVar; 
someVar = (int) someVar - 3; 

A causa di questo è necessario lanciare il risultato di nuovo per (byte) per ottenere il compilatore di accettare l'incarico.

someVar = (byte) (someVar - 3); 
+0

Qualcuno può verificare se il tipo di trasmissione avviene a livello IL in someVar- = 3; esempio? Genera lo stesso codice IL? – Dested

+2

Ho appena controllato con Reflector. Il 'operatore - =' 'genera un conv.u1' a livello di IL, motivo per cui il primo frammento sta lavorando –

+5

@Dested Le regole precise vengono fornite nel linguaggio C# Specification. Esso afferma: _ "La seconda regola precedente consente a' x op = y' di essere valutato come 'x = (T) (x op y)' in alcuni contesti.La regola esiste in modo tale che gli operatori predefiniti possano essere usati come operatori composti quando l'operando sinistro è di tipo 'sbyte',' byte', 'short',' ushort' o 'char'. Anche quando entrambi gli argomenti sono di uno di questi tipi, gli operatori predefiniti produrre un risultato di tipo' int' , come descritto nella §7.3.6.2. così, senza un cast non sarebbe possibile assegnare il risultato alla operando a sinistra. "_ –

11

Ecco una copia di una tabella nella specifica CLI (ECMA 335) che specifica operandi sono validi per gli operatori numerici binari di tipo A op B, dove A e B sono gli operandi e "op" è l'operatore, come Opcodes.Sub che si sta utilizzando nel vostro frammento:

alt text

Alcune annotazioni sono tenuti con questo:

  • "native int" è IntPtr in un programma C#
  • F rappresenta un tipo in virgola mobile, doppia o galleggiante in C#
  • & rappresenta un valore di puntatore, le scatole sono ombreggiati perché sono operazioni non sicure
  • O rappresenta un riferimento all'oggetto
  • x è un'operazione non consentita.

Nota la riga e la colonna per F, entrambi gli operandi devono essere a virgola mobile, non è possibile aggiungere direttamente, per esempio, un int in doppio. Il compilatore C# gestisce questa limitazione convertendo automaticamente l'operando int in raddoppio in modo che l'operatore sia valido.

Pertinente alla tua domanda: notare anche che i tipi byte, sbyte, char, short e ushort non sono presenti. Stesso approccio, il compilatore converte gli operandi nel tipo più piccolo che può rappresentare il valore in modo che l'operatore possa essere utilizzato. Quale sarà int32. Secondo la tabella, il risultato dell'operazione sarà int32.

Ora ecco il problema: il risultato è int32 ma l'assegnazione di tale valore a un valore di byte richiede una conversione di riduzione. Da 32 bit a 8 bit. Questo è un problema perché perde punti significativi. Il compilatore C# richiede di renderlo esplicito. Riconosci essenzialmente che sai cosa stai facendo e che sei consapevole del risultato potenzialmente sorprendente.Come questo:

byte v = 255; 
v = (byte)(v + 1); 

L'operatore - = è un problema perché non esiste un modo efficace per applicare il cast richiesto. Non è espressivo nella sintassi del linguaggio. L'utilizzo di (byte) 3 non ha senso, il letterale viene comunque convertito in int32 per far funzionare l'operatore.

Hanno puntato il problema, il compilatore emette automaticamente il cast senza il tuo aiuto.

+0

questo spiega il motivo per cui io sono in grado di utilizzare la riflessione per lanciare in modo implicito tra i tipi. – fusi