C # Farklı sonuç döndüren ifadeleri değiştirin


13

Projelerimden birinde C # 8'e geçtim. Ve tüm switchifadelerimi ifadelere taşıdım. Ancak projemin farklı çalışmaya başladığını ve bunun switchifade yüzünden olduğunu öğrendim . Örneğin bu kodu alalım

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(),
        };
    }
}

Sonucu bir yorum olarak yazdım, ancak tl; dr klasik anahtar kullanıldığında değeri beklenen Türdeki değeri döndürür, ancak anahtar ifadesi kullanıldığında, "Double" türünü döndürür byte[]. değerin bayt değeri.

İkisi arasındaki fark nedir? Neyi özledim?


1
Bunun neden ve nasıl olduğunu tam olarak açıklayamıyorum, ancak kodunuzun burada ayrıştırılmış bir versiyonuna baktığınızda ( gist.github.com/MaDOS/4904683d461d022e4b24f4080009ae5e ) derleyicinin tüm olası geri dönen türlerin fark ettiğini görüyorsunuz ifadesi bir ikiliye sığacak ve döndürülecek her sonucu saklayacağı bir ikiliyi otomatik olarak bildirecektir. ( gist.github.com/MaDOS/… )
Robin B

Yanıtlar:


17

Switch deyim formunuzda, her bir kol doğrudan bir değer döndürüyor. Sayısal türden doğrudan dönüştürülür object, çünkü yöntemin etkili bir şekilde dönüş şekli budur.

Anahtar ifade formunuz biraz farklı. Önce anahtar ifadesinden bir sonuç çıkarır, ardından bu sonucu bildirilen döndürme türüne dönüştürür. Peki, anahtar ifadesinin türü nedir? Anahtar ifadesinin kollarındaki bireysel ifadelerin tüm türlerinden "en iyi" tiptir.

Tüm bu türler dolaylı olarak double(türlerin kendisinden biridir) dönüştürülebilir, bu yüzden en iyi türdür. Dolayısıyla, anahtar ifade yönteminiz şuna eşittir:

public static dynamic CastToTypeExpression(dynamic value, DataType type)
{
    double result = 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(),
    };
    return result;
}

Bu "en iyi türü", örtülü olarak yazılan dizileri kullanarak bir anahtar ifadesi kullanmadan görebilirsiniz:

var array = new[]
{
    (byte) 0, 0.0, (short) 0, 0,
    0L, 0f, (ushort) 0, 0U, 0UL
};

Burada tür arrayolduğu anlaşılmaktadır double[].

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.