Ich habe bei einem meiner Projekte zu C # 8 gewechselt. Und ich habe alle meine switch
Aussagen auf Ausdrücke verschoben. Ich fand jedoch heraus, dass mein Projekt anders funktionierte und ich fand heraus, dass es am switch
Ausdruck lag. Holen wir uns diesen Code zum Beispiel
class Program
{
public enum DataType
{
Single,
Double,
UInt16,
UInt32,
UInt64,
Int16,
Int32,
Int64,
Byte
}
static void Main(string[] args)
{
dynamic value1 = 5;
dynamic value2 = 6;
var casted = CastToType(value1, DataType.Int16);
var casted1 = CastToTypeExpression(value2, DataType.Int16);
var type = casted.GetType(); // Int16
var type1 = casted1.GetType(); // Double
var bytes = BitConverter.GetBytes(casted); // byte arr with 2 el => [5, 0] <- expected behavior
var bytes1 = BitConverter.GetBytes(casted1); // byte arr with 8 el => [0, 0, 0, 0, 0, 0, 24, 64]
}
public static dynamic CastToType(dynamic value, DataType type)
{
switch (type)
{
case DataType.Byte:
return (byte)value;
case DataType.Double:
return (double)value;
case DataType.Int16:
return (short)value;
case DataType.Int32:
return (int)value;
case DataType.Int64:
return (long)value;
case DataType.Single:
return (float)value;
case DataType.UInt16:
return (ushort)value;
case DataType.UInt32:
return (uint)value;
case DataType.UInt64:
return (ulong)value;
default: throw new InvalidCastException();
}
}
public static dynamic CastToTypeExpression(dynamic value, DataType type)
{
return type switch
{
DataType.Byte => (byte)value,
DataType.Double => (double)value,
DataType.Int16 => (short)value,
DataType.Int32 => (int)value,
DataType.Int64 => (long)value,
DataType.Single => (float)value,
DataType.UInt16 => (ushort)value,
DataType.UInt32 => (uint)value,
DataType.UInt64 => (ulong)value,
_ => throw new InvalidCastException(),
};
}
}
Ich habe das Ergebnis als Kommentar geschrieben, aber tl; dr, wenn der klassische Schalter verwendet wird, gibt der Wert den Wert im erwarteten Typ zurück, aber wenn der Schalterausdruck verwendet wird, gibt er den Typ "Double" zurück, was zu einem anderen Wert führt, wenn der Wert byte[]
abgerufen wird Bytes des Wertes.
Was ist der Unterschied zwischen den beiden? Was vermisse ich?
Antworten:
In Ihrem switch- Anweisungsformular gibt jeder Arm direkt einen Wert zurück. Es wird direkt vom numerischen Typ in konvertiert
object
, da dies effektiv der Rückgabetyp der Methode ist.Ihre Switch Ausdruck Form ist etwas anders. Es extrahiert zuerst ein Ergebnis aus dem switch-Ausdruck und konvertiert dieses Ergebnis dann in den deklarierten Rückgabetyp. Was ist die Art des Schalterausdrucks? Es ist der "beste" Typ aus allen Typen der einzelnen Ausdrücke in den Armen des Schalterausdrucks.
Alle diese Typen können implizit in konvertiert werden
double
(dies ist einer der Typen selbst). Das ist also der beste Typ. Ihre Switch-Ausdrucksmethode entspricht also:Sie können diesen "besten Typ" ohne Verwendung eines Schalterausdrucks mit implizit typisierten Arrays sehen:
Hier ist die Art der zu
array
entnehmen ist , zu seindouble[]
.quelle