C#String地址、拼接性能学习

  •  String类型不可变。定义string变量时会在堆上分配存储空间,而对该变量进行值变更时会重新分配一个存储空间,且保留原存储空间。

  测试思路:获取string类型变量值变更前后的存储空间地址,判断地址是否相同。

      获取引用类型地址代码:     

        public static string GetMemory(Object o) 
        {
            GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned);
            IntPtr addr = h.AddrOfPinnedObject();
            return "0x" + addr.ToString("X");
        }

      测试代码:

            string str= "hello";
            Console.WriteLine(GetMemory(str));
            str = "hi";
            Console.WriteLine(GetMemory(str));

      测试结果:

C#String地址、拼接性能学习_第1张图片

     测试表明:string类型变量赋值完成后一旦修改值,实际上是重新分配一存储空间存储修改的值,原来的存储空间保留并保存原值。也就证明所谓的“string类型值不可变”。

  • string字符串拼接性能测试。通过循环模拟实现字符串拼接,并将所运行时间与stringbuilder实现相同功能所需时间对比。    
      public static void StringConcat(int num)
        {
            string str = "";
            for(int i = 0; i < num; i++)
            {
                str += i.ToString();
            }
        }
        public static void StringBuilderTest(int num)
        {
            StringBuilder builder = new StringBuilder();
            for(int i = 0; i < num; i++)
            {
                builder.Append(i.ToString());
            }
            string str = builder.ToString();
        }

    测试代码:

        int num = 1000;
            do
            {
                int start = Environment.TickCount;
                /******使用字符串连接构建字符串******/
                StringConcat(num);
                int middle = Environment.TickCount;

                /******使用StringBuilder构建字符串******/
                StringBuilderTest(num);
                int end = Environment.TickCount;

                int t1 = middle - start;
                int t2 = end - middle;
                Console.WriteLine("循环次数:{0},StringBuilder:{1}ms,字符串拼接:{2}ms", num, t2, t1);
                num = (int)(num * 1.5);
            } while (num < 1000000);

    测试结果:

    C#String地址、拼接性能学习_第2张图片

    结果表明:大量字符串连接性能很差,这当然是由string类型值不可变特性确定的,解决方案是采用stringbuilder代替。

 

你可能感兴趣的:(C#String地址、拼接性能学习)