C # สลับนิพจน์ที่ส่งคืนผลลัพธ์ที่ต่างกัน


13

ฉันเปลี่ยนเป็น C # 8 ในโครงการใดโครงการหนึ่งของฉัน และฉันได้ย้ายswitchประโยคทั้งหมดของฉันไปยังนิพจน์ อย่างไรก็ตามฉันพบว่าโครงการของฉันเริ่มทำงานแตกต่างกันและฉันพบว่าเป็นเพราะการswitchแสดงออก ให้รับโค้ดนี้เป็นตัวอย่าง

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

ฉันเขียนผลลัพธ์เป็นความคิดเห็น แต่ tl; dr เมื่อใช้สวิตช์คลาสสิกการส่งค่ากลับค่าในประเภทที่คาดไว้ แต่เมื่อใช้การแสดงออกของสวิตช์จะส่งคืนประเภทของ "คู่" ซึ่งจะแตกต่างกันbyte[]เมื่อได้รับ ไบต์ของค่า

ความแตกต่างระหว่างสองคืออะไร ฉันคิดถึงอะไร


1
ฉันไม่สามารถอธิบายได้อย่างชัดเจนว่าทำไมและสิ่งนี้เกิดขึ้นได้อย่างไร แต่ถ้าคุณดูโค้ดที่แปลแล้วที่นี่ ( gist.github.com/MaDOS/4904683d461d022e4b24f4080009ae5e ) คุณสังเกตว่าคอมไพเลอร์กลับมาเป็นไปได้ทั้งหมด ของนิพจน์จะพอดีกับ double และประกาศ double โดยอัตโนมัติซึ่งจะเก็บผลลัพธ์ใด ๆ ที่จะถูกส่งคืน ( gist.github.com/MaDOS/… )
Robin B

คำตอบ:


17

ในแบบฟอร์มใบแจ้งยอดสวิตช์ของคุณแขนแต่ละข้างจะคืนค่าโดยตรง มันแปลงจากประเภทตัวเลขโดยตรงobjectเป็นเพราะมันเป็นชนิดส่งคืนของวิธีการได้อย่างมีประสิทธิภาพ

รูปแบบนิพจน์สวิตช์ของคุณแตกต่างกันเล็กน้อย ก่อนจะแยกผลลัพธ์จากนิพจน์สวิตช์จากนั้นแปลงผลลัพธ์นั้นเป็นชนิดส่งคืนที่ประกาศไว้ แล้วสวิตช์นิพจน์ประเภทใด เป็นประเภท "ดีที่สุด" จากทุกประเภทของนิพจน์ส่วนบุคคลในแขนของการแสดงออกของสวิตช์

ประเภทเหล่านั้นทั้งหมดสามารถถูกแปลงเป็นdouble(ซึ่งเป็นประเภทหนึ่ง) โดยปริยายดังนั้นจึงเป็นประเภทที่ดีที่สุด ดังนั้นวิธีการแสดงสวิทช์ของคุณเทียบเท่ากับ:

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;
}

คุณสามารถดู "ประเภทที่ดีที่สุด" นี้โดยไม่ใช้นิพจน์สวิตช์โดยใช้อาร์เรย์ที่พิมพ์โดยนัย:

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

ที่นี่ประเภทของการอนุมานที่จะเป็นarraydouble[]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.