将对象转换为双倍的最快方法?

将对象转换为double的最快方法是什么? 我现在正处于一段代码中,其中包括:

var d = double.TryParse(o.ToString(), out d); // o is the Object... 

首先想到的是将其重写为

 var d = Convert.ToDouble(o); 

但实际上会更快吗?

编辑:除了运行配置文件(顺便说一下,我强烈建议任何开发人员使用JetBrains dotTrace ),我运行了Reflector,这帮助我提出了以下内容(或多或少相关的代码部分):

 if (o is IConvertible) { d = ((IConvertible)o).ToDouble(null); } else { d = 0d; } 

原始代码double.TryParse()在140ms内执行。 新代码在34ms内执行。 我几乎可以肯定这是我应该采取的优化路径,但在我这样做之前,有没有人看到我的“优化”代码存在任何问题? 在此先感谢您的反馈!

你必须做大量的这些,以便有任何意义,花时间在这上面。 但是,我不是来判断:

所以,你的代码是这样的:

 if (o is IConvertible) { d = ((IConvertible)o).ToDouble(null); } else { d = 0d; } 

我想知道你是否会更好

 IConvertible convert = o as IConvertible; if (convert != null) { d = convert.ToDouble(null); } else { d = 0d; } 

为您节省双重演员。

我尝试了以下方法。

  • double.TryParse
  • double.Parse
  • Convert.ToDouble

我使用了以下代码。

 public static void Main() { string text = "3.14"; var timer = new Stopwatch(); timer.Start(); for (int i = 0; i < 10000000; i++) { double d; d = Convert.ToDouble(text); //double.TryParse(text, out d); //d = double.Parse(text); } timer.Stop(); Console.WriteLine("Time=" + timer.Elapsed.ToString()); Console.ReadLine(); } 

在我的机器上,我看到了这些结果。 我平均进行了3次不同的跑步。

  • double.TryParse = 4.45秒
  • double.Parse = 4.45秒
  • Convert.ToDouble = 4.75秒

当然,我使用了可转换的字符串。 如果字符串不可转换,那么我非常怀疑double.TryParse将是最快的。

使用System.Diagnostics.Stopwatch创建一个小型测试应用程序,看看哪个更快。 虽然我认为这不会产生有价值的差异。 纯粹为了可读性,我会选择Convert.ToDouble

首先,如果您真的想知道哪个更快,您应该编写一个快速测试(使用您希望处理的数据)并为每个选项计时。 在不知道(或可能是)的情况下,很难判断。 我怀疑你不会看到太大的不同。

其次,除非你在代码的一个极其时间关键的部分调用这段代码,并称它为数千次启动时间,否则我怀疑它真的很重要。 写好,干净的代码, 然后优化。

你可能会尝试做几件不同的事情,这取决于o是什么类型的东西。 它可能是

a)盒装双,你只想取消它:

 object o = 53.2; double d = (double)o; 

b)一些其他类型,值或引用,有一些转换为double可用(实现IConvertible.ToDouble())你想要使用

 object o = 53.2M; // a System.Decimal double d = Convert.ToDouble(o); 

要么

c)具有默认字符串表示的东西,可以解析为double

 object o = "53.2"; double d; bool convertedOK = double.TryParse(o.ToString(), out d); 

在某种意义上,选项c是最长的一种方式; 你正在接受你的对象,询问它的字符串表示,然后尝试解析该字符串以获得双精度。 如果你不需要这样做,那就太笨了,在40,000个调用的例子中,它将创建并丢弃40,000个字符串……

如果您知道您的对象将始终包含实现转换为double的内容,则可以跳过所有内容并转到选项b。 如果你知道你的对象只是一个盒装双,那么选择最简单的选项(a)来取消它。

如果你真的不知道将会是什么,也许这些方面的东西对你有用吗?

 double d = (o is double) ? (double)o : (o is IConvertible) ? (o as IConvertible).ToDouble(null) : double.Parse(o.ToString()); 

(注意:如果o包含实现IConvertible但无法转换为double的内容,或者无法将其字符串表示forms解析为double,则此方法无效)

我还没有说过相对速度,但是如果拆箱比转换成字符串然后解析要快得多(除非优化器非常聪明),我会感到惊讶。

使用.NET秒表在LINQPad中进行快速测试表明存在很大差异。

 IEnumerable myData = new List() { "53.2", 53.2M, 53.2D }; const int iterations = 10000000; var sw = new Stopwatch(); var results = new List(); foreach (var o in myData) { sw.Reset(); sw.Start(); for (var i=0; i < iterations; i++) { double d = (o is double) ? (double)o : (o is IConvertible) ? (o as IConvertible).ToDouble(null) : double.Parse(o.ToString()); } sw.Stop(); results.Add($"{o.GetType()}: {iterations} iterations took {sw.ElapsedMilliseconds}ms"); } results.Dump(); 

在我的电脑上给出以下结果

 System.String: 10000000 iterations took 1329ms System.Decimal: 10000000 iterations took 402ms System.Double: 10000000 iterations took 38ms