Fastest Way for Converting an Object to Double?

前端 未结 5 1300
故里飘歌
故里飘歌 2021-01-01 17:32

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         


        
5条回答
  •  灰色年华
    2021-01-01 17:59

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

    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 
    

    提交回复
    热议问题