代码之家  ›  专栏  ›  技术社区  ›  Dan McClain

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

  •  40
  • Dan McClain  · 技术社区  · 17 年前

    以下哪种代码是转换某些对象x的最快/最佳实践?

    int myInt = (int)x;
    

    int myInt = Convert.ToInt32(x);
    

    int myInt = Int32.Parse(x);
    

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

    我很好奇,对于在Convert中有方法的数据类型,哪一种执行速度最快,而不仅仅是int。我只是以int为例。

    编辑:这种情况是从数据表获取信息引起的。(int)仍能以最快的速度工作吗?

    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 回复  |  直到 17 年前
        1
  •  83
  •   Keith    17 年前

    这取决于你对x的期望

    如果x是一个装箱整数,那么 (int)x

    如果x是一个字符串,但肯定是一个有效数字,那么 int.Parse(x) 是最好的

    int.TryParse(x)

    如果您不知道x是什么(可能是字符串或带框的int),那么 Convert.ToInt32(x) 这是最好的。

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

        2
  •  33
  •   Joel Coehoorn    17 年前

    最快的!=最佳实践!

    (int) 几乎可以肯定是最快的,因为它是一个操作符而不是一个函数调用,但它只在某些情况下工作。

    最佳实践是使用最多的资源 可读的 (国际) TryParse() . 有时是 Convert.ToInt32() .

        3
  •  21
  •   demoncodemonkey    11 年前

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

    (这适用于所有“什么是最快的:”问题)


    在我年轻的时候,我在一定程度上轻率地发表了上述言论,但我仍然同意其观点。花时间去创造一个这样的问题是不值得的,问问其他人,他们认为在每次不到1毫秒的两到三次操作中,哪一次更快。

    在日常使用中,一个周期可能比另一个周期长一两个周期,这一事实几乎可以忽略不计。如果您在将数百万个对象转换为整数时发现应用程序中存在性能问题, 那是 您可以在其中分析 代码,您将很容易地测试int转换是否实际上是瓶颈。

    而今天是对象int转换器,明天你可能会认为你的对象DateTime转换器花了很长时间。你是否会提出另一个SO问题来找出最快的方法是什么?

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

        4
  •  18
  •   dr. evil    17 年前

    int myInt = (int)x; 应该是最快的选择。否则 TryParse 将帮助您在没有异常缓慢的情况下正确完成。

    (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 
    

    转换为32=

    .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 
    
        5
  •  12
  •   Community Mohan Dere    6 年前

    当我对不同方法之间的性能差异有疑问时,我通常会在我的MeasureIt副本中创建一个新条目,这是一个从大型网站免费下载的条目 MSDN article

     
    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);
        });
    }
    
        6
  •  6
  •   Surgical Coder    17 年前

    最佳实践是TryParse,如果它有效的话,你可以看到它的结果——否则你可能会遇到异常

        7
  •  2
  •   fractos    17 年前

    因此,如果您预先知道代码的类型,并且能够多次命中该代码段,那么直接将其转换而不是在必要时进行转换是值得的。

        8
  •  1
  •   Janosch    14 年前

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

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

        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
    
        9
  •  1
  •   SysDragon    13 年前

    事实并非如此。快速转换为直接转换:

    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
    
        10
  •  0
  •   Matthias Meid    17 年前

    Parse TryParse 与字符串一起工作 String 解析对象的表示(请参见MSDN)。

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

    Convert 类,但强制转换仅适用于实际上已经是整数但不是强类型的对象。

    马蒂亚斯

        11
  •  0
  •   dan-gph    17 年前

        12
  •  0
  •   nothrow    17 年前

    (int)字符串上的转换不起作用,所以我不测试它。 Convert.ToInt32反映为将值测试为null,然后调用int.Parse,因此通常应该比int.Parse()慢。

        13
  •  0
  •   GriehmForTheWin    13 年前
    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操作。对converion或parse方法的调用将需要额外的cpu操作,因此不会太快。

        14
  •  0
  •   user3810900 user3810900    11 年前

    Here are the results. 这个 若你们知道你们要转换的总是一个有效的整数,那个么你们可以使用下面的方法(上面有几个人已经回答过了):

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

    其他需要改进的技术 benchmarked 是:

    • 转换为32
    • Int32.TryParse
        15
  •  -6
  •   GateKiller    17 年前

    最后,他们都会打电话:

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

    因此,总的来说,这与以往没有什么不同。

    看一看 .Net Reflector 看看这个。