我的应用程序使用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)
?
答案 0 :(得分:128)
我在发布模式下进行了快速的非科学测试。我在两种方法中使用了两个输入:“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
的另一次投票,其中包含一些数字来支持它。
答案 1 :(得分:46)
首先,我首先使用的是double.Parse
而不是Convert.ToDouble
。
关于您是否应该使用Parse
或TryParse
:如果输入数据不正确,或者这是非常特殊的情况,您能继续吗?如果它是特殊情况,请使用Parse
并在输入错误时让它爆炸。如果它是预期的并且可以干净地处理,请使用TryParse
。
答案 2 :(得分: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
会更快。
答案 3 :(得分:7)
如果您不打算处理异常,请使用TryParse。 TryParse更快,因为它不必处理整个异常堆栈跟踪。
答案 4 :(得分:7)
我通常会尽量避免使用Convert
类(意思是:我不使用它),因为我发现它非常令人困惑:代码提供了很少的提示,因为Convert
允许,因此在这里发生了什么使用相同的代码进行很多语义上非常不同的转换。这使得很难控制程序员究竟发生了什么。
ToString
方法没有提供适当的方法来执行此操作)。
答案 5 :(得分: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.
当您抛出异常时,解析的速度会变为次要因为没有比异常慢得多。
答案 6 :(得分:3)
这里对转换类有很多讨厌......为了平衡一点,转换有一个优点 - 如果你被交给一个对象,
Convert.ToDouble(o);
如果o已经是Double(或int或任何易于转换的东西),可以轻松返回值。
使用Double.Parse或Double.TryParse非常棒,如果你已经在字符串中,但是
Double.Parse(o.ToString());
必须首先 make 要解析的字符串,具体取决于你的输入可能更贵。
答案 7 :(得分:2)
Double.TryParse IMO。
您更容易处理,您将确切地知道错误发生的位置。
然后,如果它返回false(即无法转换),你可以处理它看起来如何适合。
答案 8 :(得分:2)
我总是喜欢使用TryParse()
方法,因为它会在不必担心异常的情况下吐出成功或失败的转换。
答案 9 :(得分:1)
就个人而言,我发现TryParse
方法更容易阅读,您实际想要使用哪种方法取决于您的用例:如果可以在本地处理错误,您可能会遇到错误和来自{{ 1}}很好,否则你可能只想让例外飞行。
我希望TryParse
也更快,因为它避免了异常处理的开销。但是使用基准工具,比如Jon Skeet's MiniBench来比较各种可能性。
答案 10 :(得分:1)
这是一个有趣的老问题。我添加一个答案是因为没人注意到原始问题。
哪个更快: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指令的总数-在我更新本文时会对此进行更多介绍。
我认为代码应该正确,清晰和快速... 按此顺序!