在其中一个项目上,我已切换到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返回预期类型的​​值,但是当使用开关表达式时,返回类型为“ Double”的类型,导致不同的byte[]获取值的字节时。

两者有什么区别?我想念什么?

最佳答案

在您的switch语句表单中,每个分支都直接返回一个值。它直接从数字类型转换为object,因为这实际上是方法的返回类型。

您的开关表达形式略有不同。它首先从switch表达式中提取结果,然后将该结果转换为声明的返回类型。那么switch表达式的类型是什么?它是switch表达式中所有单个表达式类型中的“最佳”类型。

所有这些类型都可以隐式转换为double(这是类型本身之一),因此这是最好的类型。因此,您的switch表达式方法等效于:

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


您可以使用隐式类型的数组,而无需使用switch表达式即可看到此“最佳类型”:

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


在这里,array的类型被推断为double[]

关于c# - C#开关表达式返回不同的结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58743672/

10-12 00:11
查看更多