C# 中的字符串
string是C#.net 的簡單基本數據類型(CTS中除了接口、類、委托、Object)的唯一引用類型,而且有著一些特殊的地方,使用不當可能會埋下很大的隱患。
1、字符串長度和 字符串內存長度
字符串的長度是字符串的字符個數,中文字或符號也算一個字符,例如
string msg=”Hello中國!”;???????? // 感嘆號為中中文感嘆號
上面字符串長度為 8 ,字符串占用內存字節數 :11 (GB2312,一個中文字符占2個字節) ,14(UTF8) ,32(UTF32),可見占用內存字節數和編碼有關。 這個問題我見到有公司面試題里面有(給定答案是2*Len),顯然答案是錯誤的。 不指定編碼的情況下我們的系統一般默認為GB2312,內存長度為11字節,ASCII字符占一個字節,中文占2個字節。
2、字符串常量
字符串又稱為字符串常量,一旦初始化后,其值就不會改變。任何對字符串的操作都會產生新的字符串。例如插入、合并等,都會產生新的字符串,原字符串不會變。這一點要特別注意,如果復雜頻繁的字符串操作忽略了這一特點可能帶來內存溢出的風險。
3、對象淺拷貝 Object.MemberwiseClone
MemberwiseClone方法用于創建當前對象的淺表副本(淺拷貝)。其原理是將生成一個該類型的對象,將當前對象的非靜態字段復制到新對象以創建淺表副本。如果字段是值類型,則對該字段進行按位復制,創建一個值副本;如果是一個引用類型,則復制的是引用,也就是說新的淺表副本中引用類型字段也是指向原始字段值的一個引用,新對象引用類型字段的修改會影響原始對象的相應字段。 但是,對應用類型字段的規則不適用于字符串,字符串類型字段在新對象中保存的是原始字符串的副本,所以其修改不影響原始對象。
4、操作性能
開發過程中經常會對字符串進行操作,比如聯結()Contact,這個時候一定要考慮該操作需要分配的空間,生成的對象個數,否則可能帶來災難性結果,而且如果沒有這種意識,這種問題比較能檢查。
查看下面兩種方法:
public string CombineA()
{
?????? string name=”尼古拉”;
?????? return? name + “? · 耶維奇 ·? ” + “奧斯特洛夫斯基”;
}
public string CombineB()
{
????? return =”尼古拉” + “? · 耶維奇 ·? ” + “奧斯特洛夫斯基”;
}
public string CombineC()
{
?????? return? 1+ “? · 耶維奇 ·? ” + “奧斯特洛夫斯基”;
}
方法CombineA創建了3個字符串對象”尼古拉” , “ · 耶維奇 · ” ,“奧斯特洛夫斯基” , 執行了 1 次String.Contact操作;
方法CombineB創建了一個字符串對象 “尼古拉 · 耶維奇 ·? 奧斯特洛夫斯基” ,沒有執行String.Contact操作。
方法CombineC創建了一個字符串對象“· 耶維奇 ·? 奧斯特洛夫斯基”和分配類一個整型數空間,進行了一次裝箱操作和一次String.Contact操作。
其實區分以上三種方法的關鍵就是記住一句話“字符串是常量,一旦初始化就不會變”;方法B中其實是編譯時候已經優化。
原則:多次的字符串聯結操作不要用“+”或Contact方法,請改用StringBuilder對象操作, StringBuilder不會產生新的字符串空間分配;
字符串的聯結會產生新字符串資源分配,如果在一個循環中進行操作,可能造成內存溢出(字符串分配到大對象堆上)。舉一個例子,Socket接收信息,輸出到文本框中,如果使用下面寫法,運行一段時間程序就會內存溢出:
??????? txtMsg.Text+=receivedMsg;
原因是這種操作會分配新的字符串空間,隨著時間該字符串會越來越大,結果可想而知。要解決這個問題,可以使用下面方法替換:
??????? txtMsg.AppendText(receivedMsg);??? //該方法操作原理和StringBuilder.Append() 一樣
轉載于:https://www.cnblogs.com/from1991/p/5342636.html
總結
- 上一篇: 栈与队列的应用等
- 下一篇: C#基础知识学习(2)string类中的