我将 switch 语句转换为表达式并期望 value 具有相同的类型。但是,表达式返回十进制类型而不是 int。
using System;
public class Program
{
public enum SomeType
{
INT32,
DECIMAL
}
public static void Main()
{
_ = Enum.TryParse("INT32", out SomeType paramType);
object? value = null;
//
value = paramType switch
{
SomeType.DECIMAL => (decimal)2.0,
SomeType.INT32 => (int)1,
_ => throw new ArgumentOutOfRangeException($"Not expected type.")
};
Console.WriteLine(value);
Console.WriteLine(value.GetType().ToString());
value = null;
switch(paramType)
{
case SomeType.DECIMAL:
value = (decimal)2.0;
break;
case SomeType.INT32:
value = (int)1;
break;
default:
throw new ArgumentOutOfRangeException($"Not expected type.");
}
Console.WriteLine(value);
Console.WriteLine(value.GetType().ToString());
}
}
结果:
1
System.Decimal
1
System.Int32
这是为什么?你可以在这里试试:https://dotnetfiddle.net/
回答1
switch 表达式试图找到“最佳”结果类型,就像隐式类型数组一样。
给定类型 int
和 decimal
,最好的结果类型是 decimal
,因为虽然存在从 int
到 decimal
的隐式转换,但只有从 decimal
到 int
的显式转换(因为它丢失信息)。
switch 表达式会将所选“分支”的结果隐式转换为该类型,而不管它被分配给的变量的类型。
换句话说,您的代码相当于:
object? value = null;
// The compiler selects tmp here based as the best result type
// between int and decimal
decimal tmp = paramType switch { ... };
// Now the assignment performs any conversions required to assign
// to the variable
value = tmp;
如果要使 switch 表达式的结果类型为 object
,则需要确保其中一个分支返回 object
。例如:
value = paramType switch
{
SomeType.DECIMAL => (object) 2.0m,
SomeType.INT32 => 1,
_ => throw new ArgumentOutOfRangeException($"Not expected type.")
};
(使用 2.0m 只是为了展示一种更好的方式来提出 decimal
而不是投射 double
value...)
现在结果类型是 object
,在您的示例代码中,您最终会得到一个装箱的 int
,而不是在装箱之前将 int
value 转换为 decimal
。