将对象转换为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()
在140毫秒内执行。新代码在34ms内执行。我几乎可以肯定这是我应该采取的优化路径,但在我这样做之前,有没有人看到我的“优化”代码出现问题?提前感谢您的反馈!
答案 0 :(得分:14)
你必须做很多这些事情,以便在任何时候花在这上面。但是,我不是来判断:
所以,你的代码是这样的:
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;
}
为您节省双重演员。
答案 1 :(得分:6)
我尝试了以下方法。
我使用了以下代码。
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
将是最快的一次。
答案 2 :(得分:3)
使用System.Diagnostics.Stopwatch创建一个小型测试应用程序,看看哪个更快。虽然我认为这不会产生有价值的差异。纯粹是为了可读性,我会去Convert.ToDouble
。
答案 3 :(得分:1)
首先,如果您真的想知道哪个更快,您应该编写一个快速测试(使用您希望处理的数据)并为每个选项计时。在不知道o
是什么(或可能是什么)的情况下,很难判断。我怀疑你不会发现太大的不同。
其次,除非你在代码的极时间关键部分调用这段代码,并且称它有数千次启动时间,否则我怀疑它真的很重要。写好,干净的代码,然后优化。
答案 4 :(得分:0)
你可能会尝试做几件不同的事情,这取决于o是什么类型的东西。它可能是
a)盒装双,你只想取消装箱:
object o = 53.2;
double d = (double)o;
b)其他类型,值或引用,有一些转换为可用的双重(实现IConvertible.ToDouble())你想要使用
object o = 53.2M; // a System.Decimal
double d = Convert.ToDouble(o);
或
c)具有默认字符串表示形式的东西,可以解析为双重
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的内容,或者如果其字符串表示不能被解析为double,则无法工作
我还没有说过有关相对速度的任何内容,但如果取消装箱并不比转换为字符串然后进行解析(除非优化器非常聪明),我会感到惊讶。
使用.NET秒表在LINQPad中进行快速测试表明存在很大差异。
IEnumerable<object> myData = new List<object>() { "53.2", 53.2M, 53.2D };
const int iterations = 10000000;
var sw = new Stopwatch();
var results = new List<string>();
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