CodeGym /課程 /C# SELF /用 StringBuilder 處理字串的類別

用 StringBuilder 處理字串的類別

C# SELF
等級 9 , 課堂 5
開放

1. 前言

提醒一下,C# 裡的字串是 不可變的immutable)。意思就是,字串一旦建立就不能改變:任何看起來像是「改變」字串的操作,其實都會在記憶體裡創建一個新的字串。

舉個例子,當你寫:

string hello = "哈囉";
hello += " 世界!"; // 看起來 hello 變了,其實是創建了新物件!

變數 hello 會指向一個新物件,舊的(如果沒被用到)之後會被垃圾回收器清掉。如果你在迴圈裡這樣做很多次,記憶體可能會「塞爆」,效能也會突然變很差。這在你要合併成千上萬個字串時特別明顯:每一步都會創建新字串、複製所有字元,舊物件會一直等到垃圾回收,然後你的程式就開始卡卡的。

這時候我們這堂課的主角就要登場了 —— StringBuilder


using System.Text; // ← 一定要加!
StringBuilder sb = new StringBuilder("哈囉");
sb.Append(" 世界!"); // 現在字串變得又快又有效率

認識 StringBuilder

StringBuilderSystem.Text 命名空間裡的 class。它的任務就是高效地建立和組合大量字串,可以直接改變內容,不用一直創建新物件

比喻一下:
如果字串(string)像是一塊馬賽克拼圖,每次只能整塊換掉,那 StringBuilder 就像是磁鐵白板,你可以一直「貼」或「拿掉」那些拼圖,不用每次都換一塊新白板。

什麼時候該用 StringBuilder

  • 如果你要重複改變字串(尤其是在迴圈裡)。
  • 如果你要從很多小片段組合成一大段文字。
  • 如果你很在意速度或記憶體用量。

什麼時候不用?

  • 如果你只做 1-2 個簡單的字串操作 —— 用一般 string 比較簡單又好讀。
  • 如果你真的(不知道為什麼)想保留每個字串的狀態。

2. 建立和基本操作 StringBuilder

引用命名空間

開始用很簡單:別忘了加上命名空間。

using System.Text;// ← 一定要加!

建立新字串的方法


StringBuilder sb1 = new StringBuilder();            // 空的
StringBuilder sb2 = new StringBuilder("開始");     // 有初始文字
StringBuilder sb3 = new StringBuilder(100);         // 預留 100 個字元

主要方法

var sb = new StringBuilder("開始");
sb.Append(" + 加了新文字"); 			// 加到最後面
sb.AppendLine("(這個會自動換行)"); 	// 加上 \n
sb.Insert(0, "起點: "); 						// 從第 0 個位置插入
sb.Remove(0, 7); 								// 從第 0 個位置刪掉 7 個字元
sb.Replace("文字", "STRING"); 					// 把所有 "文字" 換成 "STRING"
string result = sb.ToString(); 					// 取得最後的字串

3. StringBuilder 的效率

範例:效能比較

假設你要把 10 000 個數字串在一起(比如你要印出所有同學的學號):

天真做法(string

string text = "";
for (int i = 0; i < 10000; i++)
{
    text += i + " "; // 每次都創建新字串!
}
Console.WriteLine(text.Substring(0, 100) + "..."); // 只印前 100 個字元

最佳做法(StringBuilder

var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
    sb.Append(i).Append(' '); // 可以連著加!
}
Console.WriteLine(sb.ToString().Substring(0, 100) + "...");

差別在哪?
第一種會慢很多,也會吃掉更多記憶體。第二種又快又省記憶體。

4. StringBuilder 最常用的方法

Append —— 加入字串或其他型別(會自動轉成字串):

sb.Append("文字");
sb.Append(123); // 123 會變成 "123"
sb.Append('!'); // 字元

AppendLine —— 加入字串 + 換行符號:

sb.AppendLine("字串"); // 會加 "字串\n"

Insert —— 在指定位置插入字串:

sb.Insert(0, "Hello, "); // 插到最前面

Remove —— 刪掉幾個字元:

sb.Remove(3, 4); // 從第 3 個位置開始刪 4 個字元

Replace —— 把所有子字串或字元換掉:

sb.Replace("old", "new");
sb.Replace('a', 'A');

ToString —— 取得最終字串。

截斷字串

string 不一樣,StringBuilder 物件可以直接設定新的長度,字串會被截斷到那裡。

sb.Length = 10; // 超過第 10 個字元的都會消失!

5. 使用細節和常見錯誤

為什麼 ToString() 很重要

你在用 StringBuilder 的時候,手上拿的不是字串,而是一個特殊物件。很多方法(像 Console.WriteLine)可以直接吃這個物件,因為它會自動轉成字串,但有時你會遇到驚喜 —— 如果你不小心跟一般字串比較,或像這樣:

if (sb == "哈囉") { ... } // 哎呀!這不會 work,就算 sb 裡面是 "哈囉"

結果會是 false:因為比較的是不同型別的物件,不是字串。

正確做法:

if (sb.ToString() == "哈囉") { ... }

可變性

string 不一樣,StringBuilder可變的(mutable)!同一個物件可以一直改內容,這就是它快的原因。

記得最後要用 ToString(),不然你拿到的會是像 System.Text.StringBuilder 這種奇怪的東西,不是字串。

緩衝區大小和自動擴充

StringBuilder 內部其實是存一個字元陣列。如果你一開始就知道要「搞」很長的字串,可以在建構子的時候給預期長度 —— 這樣會快一點。

var bigBuilder = new StringBuilder(50000); // 預計 5 萬個字元

但如果你估錯也沒關係!StringBuilder 會自己擴充緩衝區,只是會慢一點點。

記憶體爆掉?

理論上,如果你完全沒節制加了幾十億個字元,還是有可能遇到 OutOfMemoryException,但現實中幾乎不會發生啦。

2
任務
C# SELF, 等級 9, 課堂 5
上鎖
使用 `StringBuilder` 方法修改字串
使用 `StringBuilder` 方法修改字串
2
任務
C# SELF, 等級 9, 課堂 5
上鎖
用 `StringBuilder` 來組成數字清單
用 `StringBuilder` 來組成數字清單
1
問卷/小測驗
字串操作,等級 9,課堂 5
未開放
字串操作
進階字串操作
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION