Double.TryParse 或 Convert.ToDouble - 哪个更快更安全?
Posted
技术标签:
【中文标题】Double.TryParse 或 Convert.ToDouble - 哪个更快更安全?【英文标题】:Double.TryParse or Convert.ToDouble - which is faster and safer? 【发布时间】:2010-10-09 20:13:51 【问题描述】:我的应用程序使用 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); 相同。返回真; 捕捉 返回错误; 。 Convert 本质上是一个包含一堆重载的包装器。你怎么做没有区别。但正如 Jon 所指出的,请考虑如何处理错误的输入。 Double.TryParse 与包裹在 try..catch 中的 double.Parse 不同。语义相同,但代码路径不同。 TryParse 首先使用内部 Number.TryStringToNumber 验证字符串是否为数字,而 Parse 假定它已经是数字/双精度数。 【参考方案1】:我在发布模式下做了一个非科学的快速测试。我在两种方法中都使用了两个输入:“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
的另一票,并附有一些数字来支持它。
【讨论】:
除了上面提到的这些,我刚刚发现Convert.ToDouble()会抛出一个带有科学计数法数字的异常。考虑一下: double toDouble = Convert.ToDouble((-1/30000).ToString()); // 将失败 double dblParse = Double.Parse((-1/30000).ToString()); // 工作正常【参考方案2】:首先,我会使用double.Parse
而不是Convert.ToDouble
。
至于你应该使用Parse
还是TryParse
:如果输入数据错误,你能继续吗,或者这是一个非常特殊的情况?如果异常,请使用Parse
,如果输入错误则让它炸毁。如果这是预期的并且可以干净地处理,请使用TryParse
。
【讨论】:
乔恩,您能否详细说明为什么您更喜欢 double.Parse 而不是 Convert.ToDouble? @dnorthut:基本上,我很少希望将 null 转换为 0(Convert.ToDouble 就是这样做的)。它通常也更灵活。我只是倾向于使用特定的方法......【参考方案3】:.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
会更快。
【讨论】:
【参考方案4】:如果您不打算处理异常,请使用 TryParse。 TryParse 更快,因为它不必处理整个异常堆栈跟踪。
【讨论】:
【参考方案5】:我通常会尽量避免使用 Convert
类(意思是:我不使用它),因为我觉得它非常令人困惑:由于 Convert
允许大量语义使用相同的代码会发生非常不同的转换。这使得程序员很难控制到底发生了什么。
因此,我的建议是永远不要使用这个类。这也不是必需的(除了数字的二进制格式,因为数字类的普通 ToString
方法没有提供适当的方法来执行此操作)。
【讨论】:
【参考方案6】:除非您 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.
当你抛出异常时,解析的速度就变得次要了,因为没有比异常慢多少。
【讨论】:
【参考方案7】:这里的 Convert 类很多人讨厌...只是为了平衡一点,Convert 有一个优势 - 如果你拿到一个对象,
Convert.ToDouble(o);
如果 o 已经是 Double (或 int 或任何易于转换的对象),则可以轻松返回值。
如果您已经将 Double.Parse 或 Double.TryParse 放在字符串中,那么使用它会很棒,但是
Double.Parse(o.ToString());
必须先制作要解析的字符串,这取决于您的输入,这可能会更昂贵。
【讨论】:
+1:我明白你的观点,在 System.Object 中用数字解析盒装数字/字符串非常容易,而不是大量的类型检查。但基本上我同意其他答案:Convert.ToSomething()
比 Parse/TryParse 贵得多,尤其是在迭代上下文中
对我来说,Convert.ToDouble(o) 有一些简单的出局,如果盒子里的东西已经是一个数字,但 Convert 的真正杀手是它没有 .TryToDouble(o , 出 d);考虑到异常的昂贵程度(以及您对输入的信心(或不相信)),这是 Convert 的一大笔额外费用。【参考方案8】:
Double.TryParse IMO。
你更容易处理,你会知道错误发生在哪里。
然后,如果它返回 false(即无法转换),您可以按照您认为合适的方式处理它。
【讨论】:
【参考方案9】:我一直更喜欢使用TryParse()
方法,因为它会吐出转换成功或失败,而不必担心异常。
【讨论】:
【参考方案10】:这是一个有趣的老问题。我正在添加一个答案,因为没有人注意到原始问题的一些内容。
哪个更快: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 指令总数 - 稍后我会更新这篇文章。
我认为代码应该是正确、清晰和快速的……按这个顺序!
【讨论】:
【参考方案11】:就我个人而言,我发现TryParse
方法更易于阅读,您实际想要使用的方法取决于您的用例:如果错误可以在本地处理,您预计会出现错误,TryParse
的 bool 是很好,否则您可能只想让异常发生。
我希望TryParse
也更快,因为它避免了异常处理的开销。但是使用基准工具,例如Jon Skeet's MiniBench 来比较各种可能性。
【讨论】:
对此答案的反馈:如果问题询问什么更快、更安全,则答案不应以“个人”开头,并包括诸如“我希望...”之类的猜测。这只是个人想法和评论,不是一个好的答案。以上是关于Double.TryParse 或 Convert.ToDouble - 哪个更快更安全?的主要内容,如果未能解决你的问题,请参考以下文章
无法让 double.TryParse 在 Linq 表达式树中工作
TryParse 适用于 var 但不适用于 C# 中的对象?