- 避免不必要的裝箱
自定義結構體
struct MyStruct { }
FCL,String自帶的拼接字符串方法
public static String Concat(params object[] args);
示例
string str1 = "str1" + 9 + false + new MyStruct() + new object();
等價於
string str1 = string.Concat("str1", 9, false, new MyStruct(), new object());
以上,發生3次裝箱,1次Concat
改為
string str1 = "str1" + 9.ToString() + false.ToString() + new MyStruct().ToString() + new object();
未發生裝箱,性能較高
結論:
拼接字符串時(+ 或 Concat),以 + 值類型.ToString()方式,不要以 + 值類型方式
-
避免分配額外的內存空間
拼接"abc"和"123"的三種方法
const string cs123 = "123"; string s123 = "123"; string str = "abc" + "123"; // 方法1 str = "abc" + s123; // 方法2 str = "abc" + cs123; // 方法3
方法1因為都是字面值,所以編譯時相當於
string str = "abc123"
,未調用Concat(),未分配內存空間方法2調用1次Concat(),分配1次內存空間
方法3等價於方法1,因為cs123是constant字面值,在編譯期就被替換成“123”。未調用Concat(),未分配內存空間
-
使用StringBuilder拼接字符串
string是不可變類型,任何修改字符串的操作都會導致開辟新的內存空間,頻繁修改字符串或拼接字符串時,使用StringBuilder更合適。
a. StringBuilder功能表現就像是一個List
b. 非托管方式分配內存
c. 默認容量16,但可以指定初始容量,不夠用時就翻倍
拓展
裝箱為什么影響性能?
引入了內存開銷 + 時間開銷
步驟:
a. 開辟堆中內存:值本身 + 類型對象指針 + 同步索引塊
b. 棧中值復制到堆
c. 實例地址返回到棧中引用變量
9.ToString()
結構體調用它的方法時並不需要先裝箱。微軟為int提供的ToString()實際調用的是非委托代碼直接操作內存返回一個字符串,而非通過CLR.
String.Format()
String.Format("{0}{1}{2}{3}",a,b,c,d);
$"{a}{b}{c}{d}"
$插值法和String.Format()底層都是使用StringBuilder拼接
測試題
StringBuilder sb = new StringBuilder();
sb.Append("t");
sb.Append("e");
sb.Append("s");
sb.Append("t");
爛代碼。使用StringBuilder拼接字面值多此一舉,采用"t" + "e" + "s" + "t"形式拼接,編譯時直接是"test",內存和時間開銷最佳。
string a = "t";
string b = "e";
string c = "s";
string d = "t";
StringBuilder sb = new StringBuilder();
sb.Append(a);
sb.Append(b);
sb.Append(c);
sb.Append(d);
好代碼。StringBuilder適合拼接運行時字符串變量。