Try   HackMD
tags: 學習記錄 C#

String 的新建與串接

字串中的每個字元都是由 Unicode 純量值所定義,也稱為 Unicode 程式碼點或 Unicode 字元的序數 (數值) 值。 每個程式碼點都是使用 UTF-16 編碼進行編碼,而編碼的每個專案的數值會以物件來表示 Char 。

字串是用來表示文字的連續字元集合。

String記憶體中物件的大小上限為 2 GB 或大約1000000000個字元。

字串的操作通常考量以下兩點:

  1. 封裝次數
  2. 記憶體消耗

字串物件的不變性

字串物件為「不可變」:它們在建立之後將無法變更。

所有看似會修改字串的 String 方法和 C# 運算子,實際上會以新的字串物件傳回結果。

string s1 = "A string is more "; string s2 = "than the sum of its chars."; // Concatenate s1 and s2. This actually creates a new // string object and stores it in s1, releasing the // reference to the original object. s1 += s2; System.Console.WriteLine(s1); // Output: A string is more than the sum of its chars.

當 s1 和 s2 的內容串連以組成單一字串時,兩個原始字串將不會被修改。 += 運算子會建立新的字串,其中包含結合的內容。 新的物件會指派給變數 s1,而先前指派給 s1 的原始物件將會被釋放以進行記憶體回收,因為已經沒有其他具有其參考的變數。

string s1 = "Hello "; string s2 = s1; s1 += "World"; System.Console.WriteLine(s2); //Output: Hello

因為對字串的「修改」實際上是建立新的字串,建立對字串的參考時,必須特別謹慎。 如果建立對字串的參考,然後「修改」原始字串,該參考將會繼續指向原始物件,而非修改字串時所建立的新物件。

String物件稱為「不可變」 (唯讀) ,因為它在建立之後無法修改其值。 出現來修改物件的方法,實際上會傳回 String String 包含修改的新物件。因為字串是不可變的,所以執行重複新增或刪除看似單一字串的字串操作常式,可能會對效能造成顯著的影響。

使用 StringBuilder 進行快速字串建立

可以使用 StringBuilder 類別,而不是對 String 字串值進行多次變更之作業的類別。與類別的實例不同的 String 是,物件是可變動的 StringBuilder ; 當串連、附加或刪除字串中的子字串時,會在單一字串上執行作業。當完成修改物件的值時 StringBuilder ,可以呼叫其方法,將 StringBuilder.ToString 它轉換成字串。

StringBuilder 類別會建立一個字串緩衝區,能在程式執行許多字串操作的情況下提供較佳的效能。 StringBuilder 字串也可重新指派內建字串資料類型所不支援的個別字元。

System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet"); sb[0] = 'C'; System.Console.WriteLine(sb.ToString()); System.Console.ReadLine(); //Outputs Cat: the ideal pet

合併字串

除了StringBuilder的串接字串,下列 String 方法可用於字串串連:

  • Concat 將一個或多個子字串合併成單一字串。
  • Join 將一個或多個子字串串連成單一元素,並在每個子字串之間加入分隔符號。

格式值

String.Format方法會使用複合格式功能,以某個物件或值的字串表示,取代字串中的一個或多個預留位置。 Format方法通常用來執行下列作業:

  • 在字串中內嵌數值的字串表示。
  • 在字串中內嵌日期和時間值的字串表示。
  • 在字串中內嵌列舉值的字串表示。
  • 若要在字串中內嵌支援介面之某個物件的字串表示 IFormattable 。
  • 以靠右對齊或靠左對齊較大字串內欄位中的子字串。

動態測試結果和程式碼

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Stopwatch stopWatch = new Stopwatch(); string titleA = "StringBuilder"; stopWatch.Restart(); string A = null; StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100000; i++) { sb.Append(i); } A = sb.ToString(); stopWatch.Stop(); Console.WriteLine("{0} \t 執行時間: {1}", titleA, stopWatch.Elapsed); string titleB = "string +"; stopWatch.Restart(); string B = null; for (int i = 0; i < 100000; i++) { B += i; } stopWatch.Stop(); Console.WriteLine("{0} \t 執行時間: {1}", titleB, stopWatch.Elapsed); string titleC = "string.concat"; stopWatch.Restart(); string C = null; for (int i = 0; i < 100000; i++) { C = string.Concat(C, i); } stopWatch.Stop(); Console.WriteLine("{0} \t 執行時間: {1}", titleC, stopWatch.Elapsed); string titleD = "string.join"; stopWatch.Restart(); string D = null; for (int i = 0; i < 100000; i++) { D = string.Join("", D, i); } stopWatch.Stop(); Console.WriteLine("{0} \t 執行時間: {1}", titleD, stopWatch.Elapsed); string titleE = "string.Format"; stopWatch.Restart(); string E = null; for (int i = 0; i < 100000; i++) { E = string.Format("{0}{1}", E, i); } stopWatch.Stop(); Console.WriteLine("{0} \t 執行時間: {1}", titleE, stopWatch.Elapsed); string titleF = "Interpolation"; stopWatch.Restart(); string F = null; for (int i = 0; i < 100000; i++) { F = $"{F}{i}"; } stopWatch.Stop(); Console.WriteLine("{0} \t 執行時間: {1}", titleF, stopWatch.Elapsed); Console.WriteLine("\nStringBuilder 和其他方法的產出內容是否相同"); Console.WriteLine(A.Equals(B)); Console.WriteLine(A.Equals(C)); Console.WriteLine(A.Equals(D)); Console.WriteLine(A.Equals(E)); Console.WriteLine(A.Equals(F));