什么是最快的:(int),Convert.ToInt32(x)或Int32.Parse(x)?

时间:2009-03-12 12:55:22

标签: c# optimization casting

以下哪个代码是转换某些对象x的最快/最佳做法?

int myInt = (int)x;

int myInt = Convert.ToInt32(x);

int myInt = Int32.Parse(x);

或在字符串's'

的情况下
int myInt;
Int32.TryParse(s, out myInt);

我很好奇哪种数据类型在转换中有一个方法,而不仅仅是整数。我只是用int作为例子。

编辑:这种情况源于从数据表中获取信息。 Will(int)仍然能以最快的速度运行吗?

从某些测试来看,当对象x = 123123123时,int表现最快,就像许多人所说的那样。当x是一个字符串时,Parse运行速度最快(注意:cast抛出异常)。我真正好奇的是,当以下列方式检索值时,它们是如何运行的:

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"]);
}

15 个答案:

答案 0 :(得分:79)

这取决于您对x的预期

如果x是一个盒装的int,那么(int)x是最快的。

如果x是字符串但绝对是有效数字,那么int.Parse(x)最好

如果x是一个字符串但它可能无效,那么int.TryParse(x)远比try-catch块快。

除了最大的循环之外,Parse和TryParse之间的差异可以忽略不计。

如果你不知道x是什么(可能是一个字符串或一个盒装的int),那么Convert.ToInt32(x)是最好的。

对于使用静态Parse和TryParse方法的所有值类型,这些通用规则也适用。

答案 1 :(得分:35)

最快!=最佳实践!

例如,(int)几乎肯定是最快的,因为它是一个运算符而不是函数调用,但它只适用于某些情况。

最佳做法是使用最不会对您的性能产​​生负面影响的可读代码,并且100次整数转换中的99次不会推动您的应用的性能。如果是,请使用最合适,最窄的转换。有时那是(int)。有时它是TryParse()。有时它是Convert.ToInt32()

答案 2 :(得分:25)

你为什么不试试几千次呢?

(这适用于所有“最快的东西:”问题)


嗯,多年来有很多事情发生了......我想我应该扩大这个答案。

上述声明在我年轻时有些轻浮,但我仍然同意其观点。花费时间创建一个SO问题是不值得的,在另外两个或三个不超过1毫秒的操作中,他们认为他们认为更快。

在日常使用中,一个人可能比另一个人长一两个周期的事实几乎肯定是微不足道的。如果您在将数百万个对象转换为整数时在应用程序中发现性能问题,就可以分析实际代码,并且您将很容易测试int转换是否实际上是瓶颈。

而今天它是object-int转换器,明天也许你会认为你的object-DateTime转换器需要很长时间。你会创建另一个SO问题来找出最快的方法吗?

至于你的情况(毫无疑问很久以来就已经解决了),正如评论中所提到的,你正在查询数据库,所以object-int转换是你最不担心的。如果我是你,我会使用你提到的任何转换方法。如果出现问题,我会使用分析器或记录来隔离呼叫。然后,当我注意到object-int转换正在进行一百万次并且转换所花费的总时间似乎相对较高时,我将改为使用不同的转换方法并重新配置。选择花费最少时间的转换方法。您甚至可以在单独的解决方案中测试它,甚至是LINQPad或Powershell等。

答案 3 :(得分:16)

如果你知道数据肯定是int,那么int myInt = (int)x;应该是最快的选择。否则TryParse将帮助您在没有异常缓慢的情况下正确使用它。

BTW:

(int)因此只能更快地取消装箱,

(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 

答案 4 :(得分:12)

当我对不同方式之间的性能差异有疑问时,我通常在我的MeasureIt副本中创建一个新条目,可以从Vance Morrison的一个伟大的MSDN article免费下载。有关更多信息,请参阅文章。

通过向MeasureIt添加一些简单的代码,我得到下面的结果,比较各种转换为int的方法的实际时间。注意从string到int的强制转换将抛出异常并且无效,所以我只添加了对我有意义的排列。


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     


要找到您感兴趣的各种类型的最佳性能,只需扩展下面的代码,这实际上是我必须添加到MeasureIt以生成上表。

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

答案 5 :(得分:6)

最佳做法是TryParse,看看结果如果有效 - 否则你可能会遇到异常

答案 6 :(得分:2)

在.Net 2中优化绑定数据网格时,我发现几乎一半的时间花在了各种对象的ToString()方法上,然后用作转换操作的输入。通过隔离这些情况并尽可能地转换为正确的类型(因为它们是从数据库中取出的行并且可以依赖类型),这导致数据绑定操作的速度大大增加。

所以,如果你事先知道事物的类型,并且你会足够多次点击这段代码,那么直接投射它而不是在必要时进行转换是值得的。

答案 7 :(得分:1)

通过alternatives from Sam Allen扩展了Eric Cosky的测试,我发现如果你知道你的字符串是一个有效的整数,那么自己解析它会快得多。

我通过以下案例扩展了测试:

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

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

通过以下实施:

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

我得到以下结果:

IntCaint.Parse                5,495
IntCaConvert.ToInt32          5,653
IntCaIntParseFast             1,154
IntCaIntParseUnsafe           1,245

答案 8 :(得分:1)

有人已经完成了基准测试。 Here are the results. 最快的方式如果您知道要转换的内容将始终是有效的int,则使用以下方法(上面已有几个人已经回答过):

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

benchmarked的其他技巧是:

  • Convert.ToInt32
  • Int32.TryParse
  • int.Parse

答案 9 :(得分:0)

不确定性能,但这些方法完全不一样。 ParseTryParse都使用字符串,解析对象的String表示形式(请参阅MSDN)。

  

将数字的字符串表示形式转换为其等效的32位有符号整数。

不确定是否正在进行转换和Convert类,但强制转换只适用于实际上已经整数但不是强类型的对象。

的Matthias

答案 10 :(得分:0)

如果您需要额外的速度,则可以轻松测试不同的选项。由于您没有测试它们,因此您不必使用它们。不要浪费你的时间进行毫无意义的微观优化!

答案 11 :(得分:0)

字符串上的

(int)转换不起作用,所以我不测试它。 Convert.ToInt32反映为测试值为null和THEN调用int.Parse,因此通常应该比int.Parse()慢。

答案 12 :(得分: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"]);
}

对于此示例,如果来自表的值确实是int值或可比数据库值,则使用

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

将是最有效的,因此“最快”是因为

row["some int value"];

将是一个在引用类型对象实例中装入的值类型int实例,因此使用显式类型转换将是最快的因为其他人说它是一个操作而不是函数调用,从而减少了所需的cpu操作。调用转换或解析方法需要额外的cpu操作,因此不能“快速”。

答案 13 :(得分:0)

这不是真的。快速转换是直接转换:

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

答案 14 :(得分:-6)

最后,他们最终都在呼唤:

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

总而言之,没有什么区别。

请查看.Net Reflector以查看此内容。