49

Which of the following code is fastest/best practice for converting some object x?

int myInt = (int)x;

or

int myInt = Convert.ToInt32(x);

or

int myInt = Int32.Parse(x);

or in the case of a string 's'

int myInt;
Int32.TryParse(s, out myInt);

I'm curious on which performs the fastest for datatypes which have a method in Convert, not just ints. I just used int as an example.

Edit: This case arose from getting information back from a datatable. Will (int) still work the fastest?

From some testing, when object x =123123123, int performs the fastest, like many have said. When x is a string, Parse runs the fastest (note: cast throws an exception). What I am really curious is how they run when the value is being retrieved in the following way:

foreach(DataRow row in someTable.Rows)
{
    myInt = (int)row["some int value"];
    myInt2 = Int.Parse(row["some int value"]);
    myInt2 = Convert.ToInt32(row["some int value"]);
}
Dan McClain
  • 11,780
  • 9
  • 47
  • 67
  • The discussion on http://stackoverflow.com/questions/586436/double-tryparse-or-double-convert-what-is-faster-and-more-safe might be helpful – Jeff Moser Mar 12 '09 at 13:39
  • 4
    seems unlikely that this part of the program is your bottleneck when you've got DB queries in play – David Heffernan Jul 17 '11 at 12:33

15 Answers15

86

It depends on what you expect x to be

If x is a boxed int then (int)x is quickest.

If x is a string but is definitely a valid number then int.Parse(x) is best

If x is a string but it might not be valid then int.TryParse(x) is far quicker than a try-catch block.

The difference between Parse and TryParse is negligible in all but the very largest loops.

If you don't know what x is (maybe a string or a boxed int) then Convert.ToInt32(x) is best.

These generalised rules are also true for all value types with static Parse and TryParse methods.

Keith
  • 150,284
  • 78
  • 298
  • 434
  • what does 'boxed int' mean? – Soheila Tarighi Jul 26 '20 at 06:13
  • 1
    @SoheilaTarighi if you have `object x = 1234;` then we would say that is _boxed_ - very basically .NET has the `int` (a value type) stored in an `object` (a reference type) we call this a _box_. If you have `object x = 1234;` then `(int) x` will just _unbox_ it, but you could have `object x = 1234; x = "abcd";` and then `(int) x` will throw an exception. – Keith Jul 27 '20 at 21:50
  • excellent response! sorry the op never accepted your answer, clean, clear, and straight to the point. – DDeathlonger Nov 29 '21 at 00:49
33

Fastest != Best Practice!

For example, (int) is almost certainly the fastest because it's an operator rather than a function call, but it will only work in certain situations.

The best practice is to use the most readable code that won't negatively impact your performance, and 99 times out of 100 an integer conversion isn't driving your app's performance. If it is, use the most appropriate, narrowest conversion you can. Sometimes that's (int). Sometimes it's TryParse(). Sometimes it's Convert.ToInt32().

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
22

Why don't you just try it a couple of thousand times?

(this goes for all "What is fastest:" questions)


Hmmm, lots of downvotes over the years... I guess I should expand on this answer.

The above statement was made with a degree of flippancy in my youth, however I still agree with its sentiment. It is not worthwhile spending time creating a SO question asking others what they think is faster out of two or three operations that take less than 1ms each.

The fact that one might take a cycle or two longer than the other will almost certainly be negligible in day-to-day usage. And if you ever notice a performance problem in your application when you are converting millions of objects to ints, that's the point where you can profile the actual code, and you'll easily be able to test whether the int conversion is actually the bottleneck.

And whereas today it's the object-int converter, tomorrow maybe you'll think your object-DateTime converter is taking a long time. Would you create another SO question to find out what's the fastest method?

As for your situation (no doubt long since resolved by now), as mentioned in a comment, you are querying a database, so object-int conversion is the least of your worries. If I was you I would use any of the conversion methods you mentioned. If a problem arises I would isolate the call, using a profiler or logging. Then when I notice that object-int conversion is being done a million times and the total time taken by that conversion seems relatively high, I would change to using a different conversion method and re-profile. Pick the conversion method that takes the least time. You could even test this in a separate solution, or even LINQPad, or Powershell etc.

demoncodemonkey
  • 11,730
  • 10
  • 61
  • 103
  • 4
    I think a few million times might be better. – WakeUpScreaming Mar 12 '09 at 13:12
  • 4
    Make that a billion while you are at it ;) – Binoj Antony Mar 13 '09 at 06:57
  • 50
    I think, it's better to have that answer, here at SO. So the thousand people that want to know that don't need to run a thousand times. It's **NOT** the best question, but it's a question that was checked for over 8K people. – Michel Ayres Apr 04 '13 at 16:51
  • 4
    @Demoncodemonkey What you say is true, but it's not an *answer*. – Yehuda Shapira Apr 23 '14 at 07:00
  • I disagree with you, in case this question will saved a lot of people time to `try it a couple of thousand times`. So instead, if you answering properly, then will save my time to scroll down. – nyconing Jan 11 '18 at 11:13
  • If everybody has to make a benchmark to see which method is the fastest that's a lot of wasted time (in sum) so in a programmer point of view it'd be more efficient to give one useful answer that everybody can look to in a couple of seconds without having to interrupt what they were doing before. – Alexandre Daubricourt Feb 26 '19 at 14:15
19

If you know that the data is definitely int then int myInt = (int)x; should be the fastest option. Otherwise TryParse will help you to get it right without the slowness of exceptions.

BTW :

(int) only unboxes therefore faster,

(int) IL =

  .locals init (
        [0] object x,
        [1] int32 Y)
    L_0000: ldc.i4.1 
    L_0001: box int32
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: unbox int32
    L_000d: ldobj int32
    L_0012: stloc.1 
    L_0013: ret 

Convert.Toint32=

.locals init (
        [0] object x,
        [1] int32 Y)
    L_0000: ldc.i4.1 
    L_0001: box int32
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
    L_000d: call int32 [mscorlib]System.Convert::ToInt32(object)
    L_0012: stloc.1 
    L_0013: ret 
dr. evil
  • 26,944
  • 33
  • 131
  • 201
12

When I have questions about performance differences between different ways of doing something specific like this, I usually make a new entry in my copy of MeasureIt, a free download from a great MSDN article from Vance Morrison. For more information please refer to the article.

By adding a simple bit of code to MeasureIt, I get the results below which compare the actual timings of the various methods of converting to int. Note the cast from string to int will throw an exception and isn't valid, so I just added the permutations that made sense to me.

 
Name                                                Median   Mean     StdDev   Min      Max    Samples       
IntCasts: Copy [count=1000 scale=10.0]              0.054    0.060    0.014    0.054    0.101    10       
IntCasts: Cast Int [count=1000 scale=10.0]          0.059    0.060    0.007    0.054    0.080    10       
IntCasts: Cast Object [count=1000 scale=10.0]       0.097    0.100    0.008    0.097    0.122    10       
IntCasts: int.Parse [count=1000 scale=10.0]         2.721    3.169    0.850    2.687    5.473    10       
IntCasts: Convert.ToInt32 [count=1000 scale=10.0]   3.221    3.258    0.067    3.219    3.418    10     

To find the best performance for the various types you are interested in, just extend the code below, which is literally all I had to add to MeasureIt to generate the above table.

static unsafe public void MeasureIntCasts()
{
    int result;
    int intInput = 1234;
    object objInput = 1234;
    string strInput = "1234";

    timer1000.Measure("Copy", 10, delegate
    {
        result = intInput;
    });
    timer1000.Measure("Cast Object", 10, delegate
    {
        result = (int)objInput;
    });

    timer1000.Measure("int.Parse", 10, delegate
    {
        result = int.Parse(strInput);
    });

    timer1000.Measure("Convert.ToInt32", 10, delegate
    {
        result = Convert.ToInt32(strInput);
    });
}
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Eric Cosky
  • 554
  • 3
  • 11
6

Best practice would be TryParse, and seeing the result of that, if it worked - otherwise you could get exceptions

Surgical Coder
  • 1,086
  • 1
  • 16
  • 25
  • I agree. Thinking about safety over speed is usually more important. – Jordan Parmer Mar 12 '09 at 13:05
  • 1
    But if you know it will cast or parse into an int, then you don't need to worry about an exception. – Samuel Mar 12 '09 at 13:19
  • How do you "know"? Unless x is an int, you can't ever know for sure! – Tundey Mar 12 '09 at 13:21
  • 1
    When pulling data from a not null int column in a database with a data reader you can "know" that the data is an int. – sgriffinusa Mar 12 '09 at 13:52
  • 1
    With SQLite, you might expect an int and in actuality get a long. Casting (int)cmd.ExecuteScalar() can fail when the returned value is a long. This goes for retrieving int primary keys and also "select count(*)". – Elan Mar 12 '11 at 17:16
  • @JordanParmer Performance is important than safety sometime. Think when you need iterate over millions buffers. – nyconing Jan 11 '18 at 11:17
3

Extending the test of Eric Cosky by alternatives from Sam Allen, i found that if you know that your string is a valid integer, then parsing it by yourself is much faster.

I extended the test by the following cases:

    timer1000.Measure("IntParseFast", 10, delegate
    {
        result = Misc.IntParseFast(strInput);
    });

    timer1000.Measure("IntParseUnsafe", 10, delegate
    {
        result = Misc.IntParseUnsafe(strInput);
    });

With the following implementations:

public static int IntParseFast(string value)
{
    int result = 0;
    int length = value.Length;
    for (int i = 0; i < length; i++)
    {
        result = 10 * result + (value[i] - 48);
    }
    return result;
}

public unsafe static int IntParseUnsafe(string value)
{
    int result = 0;
    fixed (char* v = value)
    {
        char* str = v;
        while (*str != '\0')
        {
            result = 10 * result + (*str - 48);
            str++;
        }
    }
    return result;
}

I get the following results:

IntCaint.Parse                5,495
IntCaConvert.ToInt32          5,653
IntCaIntParseFast             1,154
IntCaIntParseUnsafe           1,245
Janosch
  • 1,204
  • 1
  • 11
  • 19
2

When optimising a bound data grid in .Net 2, I found almost half the time was spent in various object's ToString() methods that were then used as the inputs of Convert operations. By isolating these cases and by casting to the correct type where possible (since they were rows taken out of a database and the types could be relied upon) this caused a massive increase in speed of that data binding operation.

So, if you know the type of the thing up front and you'll hit the piece of code enough times, it's worth the effort to cast it directly instead of converting where necessary.

fractos
  • 31
  • 3
1

this is not true. The fast conversion is direct cast:

int i = (int) stringData;

watch.Elapsed = {00:00:00.1732388}
watch2.Elapsed= {00:00:00.0878196}


 // Mesary start
                Stopwatch watch = new Stopwatch();

                watch.Start();
                for (int f = 1; f < 1000000; f++)
                {
                    item.Count = FastInt32.IntParseFast(dt.Rows[i]["TopCount"]);
                }   // Execute the task to be timed
                watch.Stop();

                Console.WriteLine("Elapsed: {0}", watch.Elapsed);
                Console.WriteLine("In milliseconds: {0}", watch.ElapsedMilliseconds);
                Console.WriteLine("In timer ticks: {0}", watch.ElapsedTicks);
                // Mesary end


                // Mesary start
                Stopwatch watch2 = new Stopwatch();

                watch2.Start();
                for (int n = 1; n < 1000000; n++)
                {
                    item.Count = (int)(dt.Rows[i]["TopCount"]);
                }   // Execute the task to be timed
                watch2.Stop();

                Console.WriteLine("Elapsed: {0}", watch2.Elapsed);
                Console.WriteLine("In milliseconds: {0}", watch2.ElapsedMilliseconds);
                Console.WriteLine("In timer ticks: {0}", watch2.ElapsedTicks);
                // Mesary end
SysDragon
  • 9,692
  • 15
  • 60
  • 89
pet
  • 11
  • 1
1

Someone's already done the benchmarking. Here are the results. The fastest way if you know what you're converting will always be a valid int, is to use the following method (which a few people have answered above) :

int value = 0;
for (int i = 0; i < str.Length; i++)
{
    value = value * 10 + (str[i] - '0');
}

Other techniques that were benchmarked were:

  • Convert.ToInt32
  • Int32.TryParse
  • int.Parse
0
foreach(DataRow row in someTable.Rows)
{
    myInt = (int)row["some int value"];
    myInt2 = Int.Parse(row["some int value"]);
    myInt2 = Convert.ToInt32(row["some int value"]);
}

For this example, if the value coming from the table is indeed an int value, or comparable database value, then using the

myInt = (int)row["some int value"];

would be the most efficient, and hence the 'fastest' becuase the

row["some int value"];

will be a value-type int instance boxed inside an reference-type object instance, so using the explicit type cast will be the quickest becuase as other people said it is an operation not a function call, thereby reducing the cpu operations required. A call to a converion or parse method would require extra cpu operations and hence not be as 'fast'.

0

Not sure about performance, but these methods aren't the same at all. Both Parse and TryParse work with string, the String representation of an object is parsed (see MSDN).

Converts the string representation of a number to its 32-bit signed integer equivalent.

Not sure about casting and the Convert class, but cast is only for objects that are already integers in fact but not strongly typed.

Matthias

Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
0

If you had the need for the extra speed, it would be easy to test the different the different options. Since you aren't testing them, you mustn't need them. Don't waste your time with pointless micro-optimizations!

dan-gph
  • 16,301
  • 12
  • 61
  • 79
0

(int) conversion on string won't work, so I dont test it. Convert.ToInt32 reflects as testing the value to null and THEN calling int.Parse, so should in general tend to be slower than int.Parse().

nothrow
  • 15,882
  • 9
  • 57
  • 104
-6

In the end, they all end up calling:

System.Number.ParseInt32(string s, NumberStyles style, NumberFormatInfo info);

So in summary, there will be no difference what so ever.

Have a look in .Net Reflector to see this.

GateKiller
  • 74,180
  • 73
  • 171
  • 204
  • is (int)x really call Int32.Parse() ? And the second question would be what the code do before callin Int32.Parse(), that'd also effect the performance. – dr. evil Mar 12 '09 at 13:01
  • (int) is just short hand for Convert.ToInt32, which calls System.Number.ParseInt32(). No difference at all. Any performance difference will only be measurable in Pico seconds. – GateKiller Mar 12 '09 at 13:04
  • GateKiller: I call BS, it's just a simple cast and unbox. – leppie Mar 12 '09 at 13:07
  • Try Parse also has an internal try catch to implement which, although small, is still overhead, making it slower (by pico seconds) than the exception throwing "parse" – DevinB Mar 12 '09 at 13:08
  • I'm with leppie: it might do that you try to cast a string, but check reflector for casting other types as well- double, long, object, etc. – Joel Coehoorn Mar 12 '09 at 13:08
  • @devinb: NO, NO, NO, TryParse does NOT use an internal try/catch. – Joel Coehoorn Mar 12 '09 at 13:09
  • To follow up: int.Parse actually call int.TryParse now and throws the exception if TryParse() fails! http://stackoverflow.com/questions/467613/parse-v-tryparse – Joel Coehoorn Mar 12 '09 at 13:13
  • @GateKiller I just check the IL and (int) just doing a simple unbox and Convert.Int32 doing other stuff (like calling GetobjectValue first) – dr. evil Mar 12 '09 at 13:19
  • @Joel: I had to actually pinch myself to make sure he actually said that. That would completely negate the purpose of the TryParses. – Samuel Mar 12 '09 at 13:21
  • NO! TryParse and Parse are implemented FROM SCRATCH, Parse isn't TryParse with exception internally. and (int)"1" really doesnt work. – nothrow Mar 12 '09 at 14:27