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)

4

11 回答 11

133

我在发布模式下做了一个快速的非科学测试。我在两种方法中都使用了两个输入:“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它的一些数字。

于 2009-02-25T15:44:38.187 回答
46

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

至于您是否应该使用Parseor TryParse: 如果输入数据错误,您是否可以继续,或者这是一个非常特殊的情况?如果它异常,请使用Parse并在输入错误时让它炸毁。如果这是预期的并且可以干净地处理,请使用TryParse.

于 2009-02-25T15:29:11.140 回答
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

于 2009-02-25T15:26:10.210 回答
7

如果您不打算处理异常,请使用 TryParse。TryParse 更快,因为它不必处理整个异常堆栈跟踪。

于 2009-02-25T15:26:59.477 回答
7

我通常会尽量避免使用Convert该类(意思是:我不使用它),因为我发现它非常令人困惑:代码对这里到底发生了什么提供了太少的提示,因为Convert允许使用相同的代码发生许多语义上非常不同的转换. 这使得程序员很难控制到底发生了什么。

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

于 2009-02-25T15:27:19.880 回答
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.

当您抛出异常时,解析的速度变得次要,因为没有比异常慢多少。

于 2011-12-19T15:11:27.187 回答
4

很多人讨厌 Convert 类在这里......只是为了平衡一点,Convert 有一个优势 - 如果你拿到一个对象,

Convert.ToDouble(o);

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

如果您已经将 Double.Parse 或 Double.TryParse 放在字符串中,那么使用它会很棒,但是

Double.Parse(o.ToString());

必须首先解析字符串,这取决于您的输入,这可能会更昂贵

于 2015-09-14T20:49:43.197 回答
2

Double.TryParse IMO。

你更容易处理,你会知道错误发生在哪里。

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

于 2009-02-25T15:26:58.273 回答
2

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

于 2009-02-25T15:28:35.540 回答
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 指令的总数 - 稍后我会更新这篇文章。

我相信代码应该是正确的、清晰的和快速的……按这个顺序!

于 2018-12-04T00:01:55.373 回答
1

就个人而言,我发现该TryParse方法更易于阅读,您实际想要使用的方法取决于您的用例:如果可以在本地处理错误,您期待错误并且 bool fromTryParse是好的,否则您可能只想让例外飞。

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

于 2009-02-25T15:29:16.537 回答