2008-09-04 13 views
19

Ich habe den folgenden C# -Code:C# numerische Konstanten

byte rule = 0; 
... 
rule = rule | 0x80; 

, die die Fehler produziert:

Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)

[Update: erste Version der Frage falsch war ... ich die Compiler Ausgabe falsch gelesen ]

die Besetzung Hinzufügen nicht beheben nicht das Problem:

rule = rule | (byte) 0x80; 

muss ich es so schreiben:

rule |= 0x80; 

Welche einfach seltsam scheint. Warum unterscheidet sich der Operator |= von dem Operator |?

Gibt es eine andere Möglichkeit, dem Compiler mitzuteilen, dass die Konstante als Byte behandelt werden soll?


@ Giovanni Galbo: ja und nein. Der Code behandelt die Programmierung des Flash-Speichers in einem externen Gerät und stellt logisch ein einzelnes Speicherbyte dar. Ich könnte es später werfen, aber das schien mehr offensichtlich. Ich denke, mein C-Erbe zeigt zu viel!

@ Jonathon Holland: die ‚als‘ Syntax ordentlicheres aussieht, aber leider scheint nicht zu funktionieren ... es produziert:

The as operator must be used with a reference type or nullable type ('byte' is a non-nullable value type)

Antwort

6
int rule = 0; 
rule |= 0x80; 

http://msdn.microsoft.com/en-us/library/kxszd0kx.aspx Die | Operator ist für alle Werttypen definiert. Ich denke, das wird das beabsichtigte Ergebnis bringen. Der Operator "| =" ist ein oder dann ein Operator, der einfach eine Abkürzung für rule = rule | ist 0x80.

Eines der nobleren Dinge an C# ist, dass Sie damit verrückte Dinge wie Missbrauch Werttypen einfach auf ihre Größe basieren können. Ein 'int' ist genau dasselbe wie ein Byte, außer dass der Compiler Warnungen ausgibt, wenn Sie versuchen, sie beide gleichzeitig zu verwenden. Einfach mit einem (in diesem Fall int) zu kleben funktioniert gut. Wenn Sie über die 64-Bit-Bereitschaft besorgt sind, können Sie int32 angeben, aber alle Ints sind int32s und werden sogar im x64-Modus ausgeführt.

+0

Wie Sie sagen, sind alle Eingänge int32, gibt die Sprach- (oder CLR-) Spezifikation diese Garantie nicht? – Eloff

+4

int ist ein C# -Alias ​​für Int32 und ist definitiv nicht das gleiche wie ein Byte. Der JIT-Compiler ist plattformunabhängig, also müssen wir es nicht sein. Die native Wortgröße, die Adressierung und die Effizienz von Operationen gegen verschiedene native Primitive sind wahrscheinlicher daran beteiligt, wie verwaltete Daten (einschließlich "Primitiven") im zugrunde liegenden System zugewiesen werden.Bedenken Sie, dass derselbe Code sowohl für .NET Micro als auch für .NET CF (für ARM für Telefon und PowerPC für XBox 360) kompiliert werden kann. Diese Systeme können sogar ihre Zahlen mit unterschiedlicher Endianz ausdrücken, was große Auswirkungen auf binäre Operationen hat. – TheXenocide

34

C# hat kein Literalsuffix für Byte. u = uint, l = lang, ul = ulong, f = float, m = dezimal, aber kein Byte. Sie müssen es umsetzen.

+2

Wie ist das passiert? – User

+2

user: es ist nicht definiert die C# -Sprache Spezifikationen. Es gibt hier ein Beispiel: http://msdn.microsoft.com/en-us/library/5bdb6693(VS.80).aspx Sie können ein Byte-Variable wie in diesem Beispiel deklarieren und initialisieren: Byte myByte = 255 ; In der vorhergehenden Deklaration wird das Integer-Literal 255 implizit von int in Byte konvertiert. Wenn das Ganzzahlliteral den Bereich von Byte überschreitet, wird ein Kompilierungsfehler auftreten. – blizpasta

9

Der Begriff, nach dem Sie suchen, ist "Literal" und leider hat C# kein Byte-Literal.

Hier ist eine Liste von all C# literals.

0

Leider ist Ihre einzige Möglichkeit, es so zu tun, wie Sie haben. Es gibt kein Suffix, um das Literal als Byte zu kennzeichnen. Das | Der Operator sieht keine implizite Umwandlung als eine Zuweisung (d. h. Initialisierung) vor.

11

Dies funktioniert:

rule = (byte)(rule | 0x80); 

Anscheinend ist der Ausdruck ‚Regel | 0x80 'gibt ein int zurück, selbst wenn Sie 0x80 als' const Byte 0x80 'definieren.

0

Apparently the expression 'rule | 0x80' returns an int even if you define 0x80 as 'const byte 0x80'.

Ich denke, die Regel Zahlen wie 0x80 Standardwerte ist in int, wenn Sie eine wörtliche Suffix enthalten. Für den Ausdruck rule | 0x80 wird das Ergebnis ein int sein, da 0x80 ein int ist und eine Regel (die ein Byte ist) sicher in int umgewandelt werden kann.

+0

Das ist falsch. Selbst wenn Sie 0x80 in ein Byte umwandeln, gibt der Operator '|' Ihnen einen int. Probiere: 'rule = Regel | (byte) 0x80; 'um zu sehen, was ich meine. Sie können jedoch die gesamte Operation in Klammern einschließen und sie alle in Byte umwandeln: 'rule = (byte) (rule | 0x80);' – Ethan

0

Gemäß dem C-Standard werden Bytes IMMER für int in Ausdrücken, sogar Konstanten, unterstützt. Solange beide Werte UNSIGNED sind, werden die höherwertigen Bits verworfen, so dass die Operation den korrekten Wert zurückgeben sollte.

Ähnlich Schwimmer fördern zu verdoppeln, usw.

Pull aus Kopie von K & R. alles drin ist es schon.

1

Fast fünf Jahre später hat niemand die Frage beantwortet.

Ein paar Antworten behaupten, dass das Problem das Fehlen eines Byte-Literals ist, aber das ist irrelevant. Wenn Sie (byte1 | byte2) berechnen, ist das Ergebnis vom Typ int. Selbst wenn "b" ein Literalsuffix für Byte wäre, wäre der Typ (23b | 32b) immer noch int.

Die akzeptierte Antwort verweist auf einen MSDN-Artikel, der behauptet, dass operator| für alle Integraltypen definiert ist, aber das stimmt auch nicht.

operator| ist nicht definiert auf byte so dass der Compiler verwendet, um seine übliche Überladungsauflösung Regeln für die Version auswählen, die auf int definiert ist. Wenn Sie also das Ergebnis einer byte zuweisen möchten, müssen Sie es werfen:

rule = (byte)(rule | 0x80); 

Es bleibt die Frage, warum tut rule |= 0x80; Arbeit?

Da die C# -Spezifikation eine spezielle Regel für die Verbundzuweisung enthält, können Sie die explizite Konvertierung weglassen. In der Verbundbelegung x op= y lautet die Regel:

if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y) , where T is the type of x, except that x is evaluated only once.