2012-02-14 92 views
4

在以下代码中,我期望var可以解析为Int64,但它会解析为double。为什么这样?为什么var会以Double而不是Long来解析?

string a = "1234"; 
bool asInt = true; 
var b = (asInt) ? Int64.Parse(a) : Double.Parse(a) ; 
Console.WriteLine(b.GetType()); 
+1

即使编译,我有点惊讶。我认为三元的两边都必须返回相同的类型,尽管我认为有一个从长到双的隐含对话 – 2012-02-14 12:32:36

+0

有。 ,)这解释了这一点。 – TomTom 2012-02-14 12:34:07

回答

12

有一个隐式转换从Int64Double而不是其他方式(由于在该方向上的精度可能损失)。

由于条件的两个“分支”都需要解析为相同类型,因此b的类型最终被推断为Double

+0

有道理。有什么办法可以在需要时创建Int64类型的变量'b',并在需要时创建Double(基于bool'asInt')?当然,在if语句中初始化它是行不通的,因为它的作用域限制在 – xbonez 2012-02-14 12:35:02

+0

@xbonez - 不在条件运算符中。该类型必须在运行时推断/确定。你可以使用'dynamic'。 – Oded 2012-02-14 12:36:38

+0

嗯...谢谢。我会研究动态的。我知道数学运算在双打上比较慢,所以我希望在不需要时不要使用双精度。我会研究动态的,但如果这不起作用,我想我会忍受它。 – xbonez 2012-02-14 12:37:52

5

您可以隐式将long投射到double

不能隐式转换一个doublelong

所以C#编译器决定了变量类型的唯一可能性是double

请参阅Implicit Numeric Conversions Table

4

因为编译器需要推断可以保存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()); 
} 
+1

那么,有没有什么办法可以做你已经做的事情,但是能够访问if-else范围之外的变量b? – xbonez 2012-02-14 12:36:41

+0

@xbonez,是的,但你应该将'b'定义为'object'类型:'object b;' – Dims 2012-02-14 12:47:48

+0

完美...这就是我一直在寻找的东西。 “对象”正是我所需要的。谢谢! – xbonez 2012-02-14 12:49:34

1

C#编译器从公分母推断两个返回类型之间的类型你三元。 Int64可以隐式转换为Double。反过来并非如此。

请注意,代码示例中布尔的状态与推断类型无关。

0

这是?:操作员的工作。它应该将所有结果都转换为一种类型。

P.S. +运营商的类似行为,你知道:

string a = "1234"; 
var b = Int64.Parse(a) + Double.Parse(a) ; 
Console.WriteLine(b.GetType()); 

P.P.S.有你想要你应该使用什么object

string a = "1234"; 
bool asInt = true; 
object b; 
if(asInt) b=Int64.Parse(a); else b=Double.Parse(a); 
Console.WriteLine(b.GetType()); 

P.P.P.S.另一种选择是:

 string a = "1234"; 
#if asInt 
     Int64 b = Int64.Parse(a); 
#else 
     Double b = Double.Parse(a); 
#endif 
     Console.WriteLine(b.GetType()); 

定义asInt中使用

#define asInt 
+0

不幸的是,'object'需要我将它转换为'Int64'或'double',然后才能对其执行任何操作,这是不可能的,因为我直到运行时才知道该类型 – xbonez 2012-02-14 12:54:04

+0

然后尝试条件编译指令,'#if'等 – Dims 2012-02-14 13:18:35

+0

如果你不依赖算术运算符,你也可以使用泛型方法和/或类型。如果你是那么你会做更多的技巧。 – Dims 2012-02-14 13:19:41

0

我很惊讶,没有人指出,如果你知道值将是一个法律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()); 

换句话说,它可能是最好的解决办法不会用三元运算符,但问题并没有给予足够的情况下就知道了。

相关问题