在下面的代码中,我希望var
得到解析为Int64
,但它被解析为double
. 为什么会这样?
string a = "1234";
bool asInt = true;
var b = (asInt) ? Int64.Parse(a) : Double.Parse(a) ;
Console.WriteLine(b.GetType());
存在从Int64
to的隐式转换,Double
但不是其他方式(由于在该方向上可能会丢失精度)。
由于条件的两个“分支”都需要解析为相同的类型,因此类型b
最终被推断为Double
.
因为编译器需要推断出一种类型,该类型可以同时保存两者的值,Int64.Parse(a)
并且Double.Parse(a)
不需要显式强制转换。如果long
是推断的,则表达式的其他部分将丢失精度。
如果需要区分类型,则必须声明两个变量并重写代码:
if (asInt)
{
var b = Int64.Parse(a); // will infer a `long`
Console.WriteLine(b.GetType());
}
else
{
var b = Double.Parse(a); // will infer a `double`
Console.WriteLine(b.GetType());
}
C# 编译器从三元的两个返回类型之间的公分母推断类型。Int64 可以隐式转换为 Double。反之则不然。
请注意,您的代码示例中的布尔值状态与推断类型无关。
我很惊讶没有人指出,如果您知道该值将是合法 long
值,则可以通过显式强制转换来更改编译器的行为,然后使用 long
.
这可能有帮助,也可能没有帮助,具体取决于确定 的值的条件asInt
,以及您打算如何处理表达式的结果。这是一个例子:
string a = "1234.56";
bool asDouble = a.Contains(".");
var b = asDouble ? (long)Double.Parse(a) : Int64.Parse(a);
Console.WriteLine(b.GetType());
事实上,在这个例子中,你不需要条件运算符;这也可以:
string a = "1234.56";
var b = (long)Double.Parse(a);
Console.WriteLine(b.GetType());
换句话说,最好的解决方案可能不会使用三元运算符,但问题并没有提供足够的上下文来了解。
这是?:
操作员的工作。它应该将所有结果转换为一种类型。
+
PS你知道的运算符的类似行为:
string a = "1234";
var b = Int64.Parse(a) + Double.Parse(a) ;
Console.WriteLine(b.GetType());
PPS 要拥有你想要的东西,你应该使用object
:
string a = "1234";
bool asInt = true;
object b;
if(asInt) b=Int64.Parse(a); else b=Double.Parse(a);
Console.WriteLine(b.GetType());
PPPS 另一种选择是:
string a = "1234";
#if asInt
Int64 b = Int64.Parse(a);
#else
Double b = Double.Parse(a);
#endif
Console.WriteLine(b.GetType());
定义 asInt 使用
#define asInt