code4life
code4life

Reputation: 15794

Fastest Way for Converting an Object to Double?

What is the fastest way to convert an object to a double? I'm at a piece of code right now, which reads:

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

First thoughts were to rewrite this as

var d = Convert.ToDouble(o);

but would that actually be faster?

EDIT: In addition to running the profile (by the way, I strongly recommend JetBrains dotTrace to any developer), I ran Reflector, and that helped me to come up with the following (more or less the relevant portion of the code):

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

The original code double.TryParse() executed in 140ms. The new code executes in 34ms. I'm almost certain that this is the optimization path I should take, but before I do that, does anyone see anything problematic with my "optimized" code? Thanks in advance for your feedback!

Upvotes: 24

Views: 67062

Answers (5)

Flory
Flory

Reputation: 2849

You must be doing a whole whopping lot of these in order to make any sense to spend any time on this. However, I am not here to judge:

So, your code is this:

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

I wonder if you would be better off with this

IConvertible convert = o as IConvertible;

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

Saves you the double cast.

Upvotes: 24

gullymiles
gullymiles

Reputation: 21

There are several different things you could be trying to do, depending on what sort of thing o is. It could be

a) a boxed double, and you just want to unbox it:

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

b) some other type, value or reference, that has some conversion to double available (implements IConvertible.ToDouble()) that you want to use

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

or

c) something which has a default string representation that can be parsed as a double

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

Option c is, in a sense, the longest way round; you're taking your object, asking for its string representation, then trying to parse that string to get a double. This is clunky if you don't need to do it, and in your example of 40,000 calls it's going to create and discard 40,000 strings...

If you know that your object will always contain something that implements a conversion to double, you can skip all that and go for option b. And if you know that your object will just be a boxed double, go for the simplest option (a) to just unbox it.

Maybe something along these lines would work for you, if you genuinely don't know what o will be?

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

(note: this won't work if o contains something that implements IConvertible but can't be converted to double, or if its string representation can't be parsed as a double)

I haven't said anything about relative speeds, but I'd be amazed if unboxing wasn't substantially quicker than converting to string and then parsing (unless the optimizer is crazy clever).

A quick test in LINQPad using the .NET Stopwatch suggests a big difference.

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();

on my PC gives the following results

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

Upvotes: 2

Brian Gideon
Brian Gideon

Reputation: 48959

I tried the following methods.

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

I used the following code.

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();
}

On my machine I saw these results. I averaged 3 different runs.

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

Of course, I used a string that was convertable. If the string is not convertable then I highly suspect double.TryParse will be the fastest by a long shot.

Upvotes: 14

Chris B.
Chris B.

Reputation: 90249

First, if you really want to know which is faster, you should write a quick test (using the data you expect to be processing) and time each option. Without knowing what o is (or is likely to be) it's very hard to judge. I suspect you're not going to see much difference.

Second, unless you're calling this bit of code in an extremely time-critical portion of your code, and calling it thousands of time to boot, I doubt it really matters. Write good, clean code, then optimize.

Upvotes: 1

Adam Houldsworth
Adam Houldsworth

Reputation: 64517

Create a small test app using System.Diagnostics.Stopwatch and see which comes out as faster. Though I would argue this wouldn't make a worthwhile difference. I'd go for Convert.ToDouble purely for readability.

Upvotes: 3

Related Questions