再写C#时常会碰到大量字串串接的场景,例如:SQL串接、Json串接、迴圈串字串、等等...,所以想要更了解编译器底层的优化机制,才不会写出效能不佳的程式,以下记录了几个常遇到的场景。
範例1:
var a = "a" + "b" + "c" + "d";
这个範例在编译时就能得知a的结果,编译器会直接合併字串,所以不会有效能上的损耗,如下:
var a = "abcd";
範例2:
var a = "a";var b = Console.ReadLine(); //input ba = a + b;
这个範例无法再编译期得知b的结果,且因字串有不可变更特性,所以第三行的a不会以第一行为基础加上b,而是一个全新的字串,结果总共会产生三个字串"a", "b", "ab",而不是"b", "ab"。
範例3:
var a = "a";var b = Console.ReadLine(); //input bvar c = "c";var d = a + b + c;
这个範例编译期无法得知结果,且以前学过在整数相加的过程中会由左到右执行,先做a+b然后暂存起来再做+c,所以我想结果应该会产生"a", "b", "c", "ab", "abc",五个字串,那这样串连很多字串时不是就很恐怖会产生一堆暂存字串,但其实编译器不会这么笨XD,编译器会把+优化成string.Concat,所以结果只会产生"a", "b", "c", "abc",四个字串,如下:
var a = "a";var b = Console.ReadLine(); //input bvar c = "c";var d = string.Concat(a, b, c);
範例4:
var a = "";for (var i = 1; i <= 5; i++){ a += i;}
这个範例会产生"1", "12", "123", "1234", "12345",字串中有大量重複的地方,会造成效能上很大的损耗,所以如果需要在迴圈内串接字串会建议使用StringBuilder来代替+,使用StringBuilder结果就只会产生一个"12345"(不包含i转成字串),如下:
var a = new StringBuilder("");for (var i = 1; i <= 5; i++){ a.Append(i);}
範例5:
var a = 1 + "1" + true + DateTime.Now;
这个範例结果会等于所有项目做字串相加,因为在+运算中只要有一个以上的项目是字串,就会转变为字串相加,遇到非字串的物件,则会使用继承object的ToString方法做转型,如下:
var a = string.Concat(new object[] {1 , "1" , true , DateTime.Now});
範例6:
var a = "a";var b = null;var c = a + b;
这个範例c的值会等于"a",字串相加时遇到null会以空字串替代,所以b会被替代为空字串。
参考文章:
如何:串连多个字串 (C# 程式设计手册)
分享一个会让人精神错乱的 .NET 观念 ( 神奇的 + 运算子 )