Laden...

Bedingte Bewertung mit konstanter Bedingung macht anschließenden Cast überflüssig, warum?

Erstellt von chriscolm vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.902 Views
C
chriscolm Themenstarter:in
112 Beiträge seit 2009
vor 12 Jahren
Bedingte Bewertung mit konstanter Bedingung macht anschließenden Cast überflüssig, warum?

Hallo,

gerade über eine Merkwürdigkeit gestolpert:


bool test = false;
byte[] testArr = new byte[] { test ? 1 : 0 };
byte[] testArr_2 = new byte[] {false ? 1 : 0 };

Kann mit jemand erklären, warum die untere Zeile anstandslos kompiliert wird, die mittlere aber nicht? Die Fehlermeldung:> Fehlermeldung:

Fehler 1 Der Typ "int" kann nicht implizit in "byte" konvertiert werden. Es ist bereits eine explizite Konvertierung vorhanden. (Möglicherweise fehlt eine Umwandlung.)

Grüße

Christian

139 Beiträge seit 2010
vor 12 Jahren

Da an dieser Stelle ein Byte-Cast fehlt.

So sollte es funktionieren:

byte[] testArr = new byte[] { (byte) (test ? 1 : 0) };

Noch kurz zur Erklärung:

byte[] testArr_2 = new byte[] { false ? 1 : 0 };

Damit erzeugst du unerreichbaren Code. Somit ist vor dem Compile klar, dass es nur 0 sein kann.

Meiner Meinung nach wird es direkt so interpretiert:


byte[] testArr_2 = new byte[] { 0 };

Dadurch entsteht keine Umwandlung in Int, wie es oben der Fall ist.

Gruss,
reloop

C
chriscolm Themenstarter:in
112 Beiträge seit 2009
vor 12 Jahren

na, mir ist schon klar, wie ich casten muss.
Mich interessiert halt, warum der Kompiler im einen Fall offenbar ein Integer sieht bzw nicht implizit casten kann, im anderen aber ein Byte.

byte[] testArr = new byte[]{true ? 1 : 0}

funzt übrigens auch. Ich meine, schließlich kann ich doch auch

byte b = 1;

deklarieren ohne dass der Kompiler meckert; hier findet ein impliziter Cast statt.

Grüße

Christian

5.657 Beiträge seit 2006
vor 12 Jahren

Wenn du einfach nur "1" schreibst, nimmt der Kompiler Integer als Datentyp an. Integer ist nicht automatisch in ein Byte umwandelbar, daher kommt dein Fehler. Es hat nichts mit dem Boolean-Datentype zu tun!

Weeks of programming can save you hours of planning

5.742 Beiträge seit 2007
vor 12 Jahren

Hallo chriscolm,

tja - auch so ein Compiler wird nur von Menschen entwickelt 😉

Ich gehe mal davon aus, dass implizite Konvertierungen zur Compilezeit im Compilingprozess vor der Behandlung des -Operators stattfinden.
Somit erkennt der Compiler nicht, dass er die 0 (ein int) gefahrlos in ein byte casten kann (geht nur, wenn der Wert in ein Byte "passt").

Bei der zweiten Variante wird vermutlich (relativ früh) eine Optimierung aktiv, die - wie das reloop schon angemerkt hat - erkennt, dass der Ausdruck immer zu "0" ausgewertet wird und setzt den Wert ein.
Daraufhin kann dann auch wieder implizit konvertiert werden.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo zusammen,

ich würde es doch eine Nuance anders sehen. Es kommt nicht darauf an, welchen Wert ein Ausdruck hat, sondern nur, ob es sich um einen literalen oder nicht-literalen Ausdruck handelt. Insofern liegt auch kein menschlicher Fehler oder ein Problem mit einer etwa übersehenen Auswirkung einer Optimierung vor, sondern alles works as designed.

Die folgenden Zitate stammen von byte (C# Reference)

you can declare and initialize a byte variable like this example:

byte myByte = 255;  

In the preceding declaration, the integer literal 255 is implicitly converted from int to byte. If the integer literal exceeds the range of byte, a compilation error will occur.

Für Integer-Literale gibt es also - wie auch schon gesagt wurde - eine implizite Konvertierung nach byte (sofern der Wertebereich stimmt).

You cannot implicitly convert non-literal numeric types of larger storage size to byte.

// Error: conversion from int to byte:  
byte z = x + y;  

Für nicht-literale Ausdrücke gibt es also keine implizite Konvertierung nach byte (selbst dann nicht, wenn der Wertebereich stimmt).

Wenn man jetzt noch weiß, dass der Compiler literale Ausdrücke bereits zur Compilezeit zu literalen Werten ausrechnet, lüftet sich der Schleier. Folgendes ist möglich und produziert keine Compiler-Fehler:

byte z = 1 + 2;

Nun sind aber auch false ? 1 : 0 und true ? 1 : 0 literale Ausdrücke die der Compiler zu den (Integer-)Literalen 0 bzw. 1 ausrechnet. Wogegen der Ausdruck test ? 1 : 0 ein nicht-literaler (Integer-)Ausdruck ist. Im ersten Fall gibt es wie besprochen eine implizite Konvertierung, im zweiten Fall nicht. Deshalb muss man im zweiten Fall explizit casten.

herbivore

PS: Unerreichbarer Code wird durch einen literale bedingte Bewertung übrigens nicht produziert (folgerichtig gibt es auch keine solche Warnung), weil daraus ja überhaupt kein ausführbarer Code generiert wird, sondern der Ausdruck schon zur Compilezeit zu einem literalen Wert ausgerechnet wird. Der literale Wert ist dann zwar schon ein Integer, der aber als solcher implizit in byte gecastet wird.

PPS: Der Compiler sieht die fraglichen Ausdrücke/Werte immer als Integer, nie als byte, aber für Interger-Literale gibt es eben die implizite Konvertierung in byte.

C
chriscolm Themenstarter:in
112 Beiträge seit 2009
vor 12 Jahren

Moin,

vielen Dank , speziell an herbivore, das ist schlüssig und nachvollziehbar.

Grüße

Christian