昨天看到关于字符串操作性能优化的帖子。

  1.使用值类型的ToString方法

  首先理解装箱和拆箱:1.装箱在值类型向引用类型转换时发生。2. 拆箱在引用类型向值类型转换时发生装箱操作和拆箱操作是要额外耗费cpu和内存资源的,所以在c# 2.0之后引入了泛型来减少装箱操作和拆箱操作消耗

  值类型ToString是不会装箱。例如:string a = a + 1;和string a= a + 1.tostring();前者会引起装箱额外消耗资源。

  2.运用StringBuilder类 

  String是不可变的。 对象是不可变的。 每次使用 System.String 类中的一个方法时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。 在需要对字符串执行重复修改的情况下,与创建新的 String 对象相关的系统开销可能会非常大。 如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder 类。 例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder 类可以提升性能。

  下面简单写个案例实践一下:

public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
        /// <summary>
        /// str + i引起装箱消耗额外资源
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public string Test1(int count)
        {
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
            {
                string a = "a";
                a = a + 1;
            }
            watch.Stop();
            float sec = watch.ElapsedMilliseconds / 1000.0f;
            return string.Format("耗时:{0}秒", sec);
        }
        /// <summary>
        /// 值类型ToString不会装箱
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public string Test2(int count)
        {
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
            {
                string a = "a";
                a = a + 1.ToString();
            }
            watch.Stop();
            float sec = watch.ElapsedMilliseconds / 1000.0f;
            return string.Format("耗时:{0}秒", sec);
        }
        /// <summary>
        /// str + i引起装箱消耗额外资源
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public string Test3(int count)
        {
            string str = "";
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
            {
                str = str + i;
            }
            watch.Stop();
            float sec = watch.ElapsedMilliseconds / 1000.0f;
            return string.Format("耗时:{0}秒", sec);
        }
        /// <summary>
        /// 使用String,在内存中创建一个新的字符串对象
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public string Test4(int count)
        {
            string str = "";
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
            {
                str = str + i.ToString();
            }
            watch.Stop();
            float sec = watch.ElapsedMilliseconds / 1000.0f;
            return string.Format("耗时:{0}秒", sec);
        }
        /// <summary>
        /// 使用StringBuilder
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public string Test5(int count)
        {
            System.Text.StringBuilder str = new System.Text.StringBuilder();
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
            {
                str.Append(i.ToString());
            }
            string result = str.ToString();
            watch.Stop();
            float sec = watch.ElapsedMilliseconds / 1000.0f;
            return string.Format("耗时:{0}秒", sec);
        }
    }

  多次运行结果可以看到Test1,Test2每次装箱引起性能消耗不是很大,当到100000000(一亿)时有一秒左右差距。Test4,Test5当运行10000时,差距零点几,当运行100000时使用StringBuilder明显性能提升,当然我们可能也用不到如此长的string字符串,以前有个项目sql语句非常复杂是通过StringBuilder拼接的,当时只知道照着用,现在才知道还可以略微提升性能。