Double.TryParse或Convert.ToDouble-哪个更快,更安全?


80

我的应用程序使用VSTO读取Excel文件,并将读取的数据添加到StringDictionary。它仅添加数位数的数据(1000 1000,2 1000,34-逗号是俄语标准中的定界符)。

有什么更好的方法来检查当前字符串是否合适?

object data, string key; // data had read

try
{
  Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
  dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
  // is not a number
}

要么

double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
  dic.Add(key, str);
}

由于以下解析算法问题,我不得不使用StringDictionary而不是Dictionary<string, double>

我的问题:哪种方法更快?哪个更安全?

打电话Convert.ToDouble(object)还是更好Convert.ToDouble(string)


仅供参考,double.TryParse与try {result = double.Parse(s ;; 返回true;} catch {return false; }。转换本质上是两个都有大量重载的包装器。怎么做都没有关系。但是正如乔恩指出的那样,请考虑如何处理错误的输入。
约翰·莱德格伦

12
Double.TryParse与使用try..catch包装的double.Parse不同。语义相同,但是代码路径不同。TryParse首先使用内部Number.TryStringToNumber验证字符串是否为数字,而Parse假定它已经是一个数字/双精度数。
杰夫·摩泽尔(

Answers:


131

我在发布模式下进行了快速的非科学测试。我在这两种方法中都使用了两个输入:“ 2.34523”和“ badinput”,并迭代了1,000,000次。

有效输入:

Double.TryParse = 646ms
Convert.ToDouble = 662 ms

与预期的相差无几。对于所有意图和目的,对于有效输入,这些都是相同的。

输入无效:

Double.TryParse = 612ms
Convert.ToDouble = ..

好吧..它运行了很长时间。我使用1,000次迭代重新运行了整个过程Convert.ToDouble,错误的输入花了8.3秒。平均下来,将需要2多个小时。我不在乎测试的基础程度如何,在无效输入的情况下,Convert.ToDouble引发异常会破坏您的性能。

因此,这是另一个支持TryParse一些数字的投票。


4
除了上面提到的内容外,我还发现Convert.ToDouble()会使用科学计数法引发数字异常。考虑一下:double toDouble = Convert.ToDouble((-1/30000).ToString()); //将失败double dblParse = Double.Parse((-1/30000).ToString()); //效果很好
Buddy Lee

46

首先,我会使用double.Parse而不是Convert.ToDouble首先使用。

关于是否应使用ParseTryParse:如果输入数据错误,是否可以继续进行操作,或者这确实是例外情况?如果异常,请使用,Parse并在输入错误时将其炸毁。如果可以预期并且可以正常使用,请使用TryParse


6
乔恩,您能详细说明为什么要使用double.Parse而不是Convert.ToDouble吗?
大卫·诺斯

10
@dnorthut:基本上,我很少希望将null转换为0(Convert.ToDouble确实如此)。通常它也更灵活。我只是倾向于使用特定的方法...
Jon Skeet

8

.NET Framework设计指南建议使用Try方法。避免异常通常是一个好主意。

Convert.ToDouble(object) 会做 ((IConvertible) object).ToDouble(null);

哪个会打电话 Convert.ToDouble(string, null)

因此,调用字符串版本更快。

但是,字符串版本只是这样做:

if (value == null)
{
    return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);

因此,double.Parse直接执行操作更快。



7

我通常尝试避免使用Convert该类(意思是:我不使用它),因为我发现它非常令人困惑:该代码很少给出关于此处实际发生情况的提示,因为Convert使用相同的代码可以进行很多语义上非常不同的转换,因此代码对。这使得程序员很难控制到底发生了什么。

因此,我的建议是永远不要使用此类。也不是必须的(数字的二进制格式除外,因为ToString数字类的常规方法没有提供执行此操作的适当方法)。


7

除非您对输入有100%的确定(这是罕见的情况),否则应使用Double.TryParse。

Convert.ToDouble will throw an exception on non-numbers
Double.Parse will throw an exception on non-numbers or null
Double.TryParse will return false or 0 on any of the above without generating an exception.

当您引发异常时,解析的速度将成为次要的,因为不会比异常慢很多。


4

这里对Convert类非常讨厌...为了保持一点平衡,Convert有一个优点-如果您将一个对象交给您,

Convert.ToDouble(o);

如果o已经是Double(或int或任何易于转换的东西),则可以轻松地返回值。

如果您已经在字符串中使用Double.Parse或Double.TryParse,则非常有用,但是

Double.Parse(o.ToString());

已去做出的字符串,第一,并根据您的输入,可能是更昂贵的解析。


1
+1:从您的角度来看,在System.Object内部解析带数字的带框数字/字符串非常简单,而无需进行大量类型检查。但基本上我也同意其他答案:Convert.ToSomething()比Parse / TryParse昂贵得多,尤其是在迭代环境中
T-moty 2015年

对我来说,如果包装盒中已经有一个数字,那么Convert.ToDouble(o)会有一些简单的输出,但是对Convert来说,真正的杀手是它没有.TryToDouble(o,out d); 鉴于异常的代价是昂贵的(以及您对输入的信心有无),这是Convert的大笔额外费用。
user1664043 2015年

2

Double.TryParse IMO。

您可以更轻松地进行处理,您将确切知道错误发生的位置。

然后,如果它返回false(即无法转换),则可以按照您认为合适的方式处理它。


2

我一直偏爱使用这些TryParse()方法,因为它会吐出成功或失败的转换而不必担心异常。


2

这是一个有趣的老问题。我添加一个答案是因为没人注意到原始问题。

哪个更快:Convert.ToDouble或Double.TryParse?哪个更安全:Convert.ToDouble或Double.TryParse?

我将详细回答这两个问题(稍后将更新答案),但首先:

为了安全起见,每个程序员在这个问题上都没有想到的是一行(强调我的意思):

它仅添加具有几位数字的数据(1000 1000,2 1000,34-逗号是俄语标准中的定界符)。

下面是此代码示例:

Convert.ToDouble(regionData, CultureInfo.CurrentCulture);

这里有趣的是,如果电子表格采用俄语数字格式,但Excel未能正确键入单元格字段,那么对Excel产生的值的正确解释是什么?

关于速度,这是关于两个示例的另一件有趣的事情:

catch (InvalidCastException)
{
    // is not a number
}

这很可能会生成如下所示的MSIL:

catch [mscorlib]System.InvalidCastException 
{
  IL_0023:  stloc.0
  IL_0024:  nop
  IL_0025:  ldloc.0
  IL_0026:  nop
  IL_002b:  nop
  IL_002c:  nop
  IL_002d:  leave.s    IL_002f
}  // end handler
IL_002f: nop
IL_0030: return

从这个意义上讲,我们可能可以比较每个程序执行的MSIL指令的总数-稍后在我更新本文时会对此进行更多介绍。

我相信代码应该正确,清晰和快速……按此顺序!


1

就我个人而言,我发现该TryParse方法更易于阅读,您实际要使用的方法取决于您的用例:如果错误可以在本地处理,则您期望错误,但从TryParse中获利是好的,否则您可能只想让例外发生。

我希望它TryParse也可以更快,因为它避免了异常处理的开销。但是,使用基准工具(例如Jon Skeet的MiniBench)来比较各种可能性。


关于此答案的反馈:如果问题询问更快,更安全的答案,则答案不应以“个人”开头,而应包含诸如“我希望...”之类的猜测。这只是个人想法和评论,不是一个好答案。
PandaWood '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.