string 與 String,大 S 與小 S 之間有關字元串的秘密 字元串是 String 類型的對象,它的值是文本。 在內部,文本被存儲為 Char 對象的順序只讀集合。 C# 字元串末尾沒有以 null 結尾的字元;因此 C# 字元串可以包含任意數目的嵌入式 null 字元(“\0”)。 字 ...
string 與 String,大 S 與小 S 之間沒有什麼不可言說的秘密
目錄
- 小寫 string 與大寫 String
- 聲明與初始化 string
- string 的不可變性
- 正則 string 與原義 string
- string 的轉義序列
- 格式化字元串
- 操作子字元串
- 字元串的 null 與 ""(空)
- 可提高性能的 StringBuilder
序
字元串是 String 類型的對象,它的值是文本。 在內部,文本被存儲為 Char 對象的順序只讀集合。 C# 字元串末尾沒有以 null 結尾的字元;因此 C# 字元串可以包含任意數目的嵌入式 null 字元(“\0”)。 字元串的 Length 屬性代表它包含的 Char
對象的數量,而不是 Unicode 字元的數量。 若要訪問字元串中的各個 Unicode 碼位,請使用 StringInfo 對象。
小寫 string 與大寫 String
在 C# 中,關鍵字 string 是 String 的別名。 因此,String 與 string 等效,也就是說您想用哪個就用哪個。String 類提供了很多用於安全地創建、操作和比較字元串的方法。此外,C# 語言還重載某些運算符來簡化常見的字元串操作。
聲明與初始化 string
請看示例:
1 static void Main(string[] args) 2 { 3 // 聲明但不初始化 4 string msg1; 5 6 // 聲明並初始化為 null 7 string msg2 = null; 8 9 // 作為一個空字元串進行初始化,用 Empty(空) 常量而不是字面值的 ""(空) 10 string msg3 = String.Empty; 11 12 // 用正則的字元串字面值進行初始化 13 string oldPath = "c:\\windows"; 14 15 // 直接以字元串初始化 16 string newPath = @"c:\windows"; 17 18 // 也可以使用 System.String 19 String content = "Hello World!"; 20 21 // 使用 const 防止 msg4 被篡改 22 const string msg4 = "I'm const!"; 23 24 // 可以使用隱式類型 var 25 var msg5 = "Hi!"; 26 27 // 使用 String 構造器進行初始化 28 char[] letters = { 'A', 'B', 'C' }; 29 string alphabet = new String(letters); 30 31 Console.Read(); 32 }
【註意】除了在使用字元數組初始化字元串時以外,不要使用 new 運算符創建字元串對象。
使用 Empty 常量值初始化字元串可新建字元串長度為零的 String 對象。零長度字元串的字元串表示形式為 ""。使用 Empty 值(而不是 null)初始化字元串可以降低發生 NullReferenceException 的可能性。我們常常會在嘗試訪問字元串之前使用靜態 IsNullOrEmpty(String) 方法驗證字元串的值。
string 的不可變性
字元串對象是不可變的:即它們創建之後就無法更改。 所有看似修改字元串的 String 方法和 C# 中的運算符,實際上都以新字元串對象的形式返回結果。 在下麵的示例中,當連接 s1
和 s2
的內容以形成一個字元串時,不會修改兩個原始字元串。 +=
運算符會創建一個包含組合內容的新字元串。 這個新對象賦給變數 s1
,而最初賦給 s1
的對象由於沒有其他任何變數包含對它的引用而釋放,將在後續被垃圾回收。
示例一:
1 static void Main(string[] args) 2 { 3 var s1 = "Hi!"; 4 var s2 = "Fanguzai!"; 5 6 //拼接 s1 和 s2,並且修改 s1 指向的值 7 s1 += s2; //即 s1 = s1 + s2; 8 9 Console.WriteLine(s1); 10 Console.Read(); 11 }
圖:var s1 = "Hi!"; var s2 = "Fanguzai!";
圖:s1 = s1 + s2; 重新修改 s1 的指向
由於“修改”字元串實際上是創建一個新字元串,因此創建對字元串的引用時必須謹慎。 如果創建了對字元串的引用,然後“修改”原始字元串,則該引用指向的仍是原始對象,而不是修改字元串時創建的新對象。
1 static void Main(string[] args) 2 { 3 var s1 = "Hi! "; 4 var s2 = s1; 5 6 //在 s1 重新賦值後,這次沒有重新修改 s2 指向的值 7 s1 += "Fanguzai!"; //即 s1 = s1 + "Fanguzai!"; 8 9 Console.WriteLine(s2); 10 Console.Read(); 11 }
圖:var s1 = "Hi!"; s2 = s1; 他們指向相同的引用地址
圖:s1 = s1 + "Fanguzai!"; 會創建一個沒有引用的 "Fanguzai!",並重新修改 s1 指向的值。
正則 string 與原義 string
如果必須嵌入 C# 提供的轉義符,則應使用正則字元串:
1 static void Main(string[] args) 2 { 3 var coluString = "Col1\tCol2\tCol3"; 4 var rowString = "Row1\r\nRow2\r\nRow3"; 5 6 Console.WriteLine(coluString); 7 Console.WriteLine("====="); 8 Console.WriteLine(rowString); 9 Console.Read(); 10 }
如果字元串文本包含反斜杠字元(例如在文件路徑中),為方便起見和提高可讀性,應使用原義字元串。由於原義字元串保留換行符作為字元串文本的一部分,因此可用於初始化多行字元串。在原義字元串中嵌入引號時請使用雙引號。下麵的示例演示原義字元串的一些常見用途:
1 static void Main(string[] args) 2 { 3 var path = @"C:\Windows"; 4 var text = @"Are you Fanguzai? 5 I'm Fanguzai!"; 6 7 Console.WriteLine(path); 8 Console.WriteLine("====="); 9 Console.WriteLine(text); 10 Console.Read(); 11 }
string 的轉義序列
【備註】編譯時,原義字元串轉換為所有轉義序列均保持不變的普通字元串。因而,如果在調試器監視視窗中查看原義字元串,則看到的將是編譯器添加的轉義字元,而不是源代碼中的原義版本。 例如,原義字元串 @"C:\temp.txt" 在監視視窗中將顯示為 "C:\\temp.txt"。
格式化字元串
格式字元串是內容可以在運行時動態確定的一種字元串。採用以下方式創建格式字元串:使用靜態 Format 方法併在大括弧中嵌入占位符,這些占位符將在運行時替換為其他值。
1 private static void Main(string[] args) 2 { 3 const string name = "Fanguzai"; 4 var s = string.Format("Hi, {0}!", name); //使用占位符 5 6 Console.WriteLine(s); 7 8 Console.Read(); 9 }
操作子字元串
子字元串是包含在字元串中的任意字元序列。 使用 Substring 方法可以基於原始字元串的一部分創建新字元串。 可以使用 IndexOf 方法搜索子字元串的一個或多個匹配項。 使用 Replace 方法可將指定子字元串的所有匹配項替換為一個新字元串。 與 Substring 方法一樣,Replace 實際上返回的也是新字元串,而不修改原始字元串。
1 private static void Main(string[] args) 2 { 3 const string s1 = "Hi, Fanguzai!"; 4 5 Console.WriteLine(s1.Substring(4)); //截取 6 Console.WriteLine(s1.Replace("Hi","Hello")); //替換 7 Console.WriteLine(s1.IndexOf(",", StringComparison.Ordinal)); //取索引 8 9 Console.Read(); 10 }
字元串的 null 與 ""(空)
空字元串是不包含字元的 System.String 對象的實例。 在各種編程方案中經常會使用空字元串表示空白文本欄位。 可以對空字元串調用方法,因為它們是有效的 System.String 對象。
var s = string.Empty;
相反,null 字元串並不引用 System.String 對象的實例,任何對 null 字元串調用方法的嘗試都會生成 NullReferenceException。 但是,可以在串聯和比較操作中將 null 字元串與其他字元串一起使用。
1 private static void Main(string[] args) 2 { 3 const string s1 = "Hi, Fanguzai!"; 4 string s2 = null; 5 var s3 = string.Empty; 6 7 var s4 = s1 + s2; //有值的字元串與 null 拼接 8 Console.WriteLine("s4: {0}", s4); 9 Console.WriteLine(""); 10 11 var isTrue = (s2 == s3); 12 Console.WriteLine("isTrue: {0}", isTrue); 13 Console.WriteLine(); 14 15 var s5 = s3 + s2; 16 Console.WriteLine("s5: {0}", s5); 17 Console.WriteLine(); 18 19 Console.Read(); 20 }
可提高性能的 StringBuilder
.NET 中的字元串操作已高度優化,大多數情況下不會顯著影響性能。但在某些應用場景中,例如在執行數百甚至好幾億次的迴圈中,字元串操作很可能會影響性能。 StringBuilder 類創建了一個字元串緩衝區,用於在程式執行大量字元串操作時提供更好的性能。 StringBuilder 字元串可以重新分配個別字元(內置字元串數據類型所不支持的字元)。例如,此代碼在不創建新字元串的情況下更改了一個字元串的內容:
1 static void Main(string[] args) 2 { 3 var sb = new StringBuilder("~ Hi! Fanguzai!"); 4 sb[0] = '^'; 5 6 Console.WriteLine(sb); 7 Console.Read(); 8 }
系列相關
《C# 知識回顧 - 表達式樹 Expression Trees》
《C# 知識回顧 - 特性 Attribute》、《剖析 AssemblyInfo.cs - 瞭解常用的特性 Attribute》《C# 知識回顧 - 委托 delegate》、《C# 知識回顧 - 委托 delegate (續)》
【博主】反骨仔
【出處】http://www.cnblogs.com/liqingwen/p/6155790.html
【參考】微軟官方文檔