views:

1685

answers:

11

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"]);
}
+5  A: 

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

pzycoman
I agree. Thinking about safety over speed is usually more important.
j0rd4n
But if you know it will cast or parse into an int, then you don't need to worry about an exception.
Samuel
How do you "know"? Unless x is an int, you can't ever know for sure!
Tundey
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
+9  A: 

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
Yeah (int) != Convert.ToInt32, Gatekiller must be smoking bad stuff :) +1
leppie
A: 

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
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
(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
GateKiller: I call BS, it's just a simple cast and unbox.
leppie
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"
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
@devinb: NO, NO, NO, TryParse does NOT use an internal try/catch.
Joel Coehoorn
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
@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
@Joel: I had to actually pinch myself to make sure he actually said that. That would completely negate the purpose of the TryParses.
Samuel
NO! TryParse and Parse are implemented FROM SCRATCH, Parse isn't TryParse with exception internally. and (int)"1" really doesnt work.
Yossarian
A: 

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

Mudu
+17  A: 

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

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

demoncodemonkey
I think a few million times might be better.
WakeUpScreaming
Make that a billion while you are at it ;)
Binoj Antony
+17  A: 

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
A: 

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!

dangph
+8  A: 

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
A: 

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

Yossarian
+2  A: 

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
+4  A: 

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);
 });
}
Eric Cosky
How about the average too? An increase sample size to a 'real world value' like 10000 at least.
leppie
You also create a ton of overhead using closures.
leppie