前言
前面的內容截至目前關於C#基礎的知識大多都講解得差不多了。
這裡做進階的補充。
如果需要呈現格式化數字時,可以使用以下的方法來處理百分比、千分位和自訂數值格式化。
百分比格式化:
double percent = 0.5;
Console.WriteLine($"百分比格式化:{percent:P}"); // 百分比格式化:50.00%
Console.WriteLine($"百分比格式化(2位小數):{percent:P2}"); // 百分比格式化(2位小數):50.00%
Console.WriteLine($"百分比格式化(1位小數):{percent:P1}"); // 百分比格式化(1位小數):50.0%
Console.WriteLine($"百分比格式化(整數):{percent:P0}"); // 百分比格式化(整數):50%
千分位格式化:
int num = 1000000;
Console.WriteLine($"千分位格式化:{num:N}"); // 千分位格式化:1,000,000.00
Console.WriteLine($"千分位格式化(無小數位):{num:N0}"); // 千分位格式化(無小數位):1,000,000
Console.WriteLine($"千分位格式化(1位小數):{num:N1}"); // 千分位格式化(1位小數):1,000,000.0
Console.WriteLine($"千分位格式化(2位小數):{num:N2}"); // 千分位格式化(2位小數):1,000,000.00
自訂數值格式化,保留小數點後2位:
double num1 = 10.1;
Console.WriteLine($"自訂數值格式化(2位小數):{num1:0.00}"); // 自訂數值格式化(2位小數):10.10
double num2 = 0.1987;
Console.WriteLine($"自訂數值格式化(2位小數):{num2:0.00}"); // 自訂數值格式化(2位小數):0.20
Console.WriteLine($"自訂數值格式化(2位小數,不顯示0):{num2:#.00}"); // 自訂數值格式化(2位小數,不顯示0):.20
StringBuilder 是什麼? StringBuilder是在 .NET 中的一個類,用於動態地建立、修改和處理字串。
與 string 不同, StringBuilder 物件是可變的,意思是可以在不創建新字串的情況下對字串進行連接和修改。這個方法在需要頻繁修改文字的情況下特別有用,例如報表生成、文字處理、日誌記錄等。
那關於string不可變跟StringBuilder可變是差異在哪裡,是甚麼意思??
不可變性: 字串 (string
) 在 .NET 中是不可變的,意思就是一旦創建,就不能修改。
我們每次對 string 執行操作(例如連接、拼接或修改),都會創建一個新的 string 實例,並將修改後的內容複製到新的實例中。這樣會導致了大量的記憶體分配和拷貝操作,也就是說這樣的操作對於大量數據將導致內存和性能開銷,特別是在迴圈中執行這些操作時。
但反過來如果您的字串是固定的,不需要在運行時進行修改,則 string 是合適的選擇。
對於簡單的字串操作,例如連接幾個固定字串或執行基本的字串搜索和替換,用 string 就夠了,因為它提供了方便的方法和運算子,並且通常具有良好的性能。
StringBuilder 的可變性: StringBuilder
被設計成可變的,它內部維護一個字符緩衝區,允許在其中添加、插入或移除字符,可以有效地執行連接和修改操作,而不需要創建新的實例。這意味著在迴圈中使用不會產生大量的字串實例,從而減少記憶體使用和提高性能。
如果需要動態修改字串或執行大量的字串連接操作,則 StringBuilder
可以提供更好的性能。
如果字串是固定的且不需要修改,或者操作相對簡單,則 string
可以更容易使用並且足夠應對需求。
為什麼使用 StringBuilder?
如果需要連接或修改大量文字時,使用 string 可能會導致性能問題,如上面不可變性裡面提到的,每次對 string 執行操作時,都會創建一個新的 string 實例。這樣就會影響到性能。
(雖然string 類型的物件最終會被 .NET 中的垃圾回收器(Garbage Collector,簡稱 GC)回收。垃圾回收器的主要作用是追蹤和回收不再被引用的物件,以釋放佔用的內存,從而確保應用程序不會耗盡系統的記憶體。)
而 StringBuilder 則通過在內部維護一個可擴展的字符緩衝區來解決這個問題,從而提供更高的性能。
如何使用 StringBuilder?
StringBuilder
實例:首先,您需要創建一個 StringBuilder 對象,通常使用 new StringBuilder() 構造函數。Append
方法:使用 Append 方法把文字附加到 StringBuilder 的內部緩衝區。這樣可以在不創建新字串的情況下串聯文字。ToString
方法:當完成所有的操作後,使用 ToString 方法將 StringBuilder 的內容轉換為最終的 string 。範例:
以下是個簡單的例子,來看看如何使用 StringBuilder 來連接大量文字:
var sb = new StringBuilder();
for (int i = 0; i < 100000; i++)
{
sb.Append("文字"); // 將文字附加到 StringBuilder
}
string result = sb.ToString(); // 將 StringBuilder 內容轉換為 string
Console.WriteLine(result.Length); // 顯示文字的長度
這樣就可以更有效率地處理大量文字數據,比較不需要擔心性能問題。在需要處理大型報表、生成大量文字的應用程序中,使用 StringBuilder 是一個重要的優化工具。
這些方法允許明確地將一種資料型別轉換為另一種,而不依賴於隱含的型別轉換規則。(ToString
和 ToInt32
)
那剛剛上面StringBuilder裡面提到的ToString方法又是甚麼??
我們常常會有機會使用到這個方法,主要適用於把對象轉換成字串表示形式。
ToString方法用於將某個資料類型(通常是數值或物件)轉換為字串。
當我們呼叫這個方法的時候會回傳一個字串,回傳的這個字串描述了這個對象裡面的內容,像是可以把一些基本數據類型(例如 int
、double
、DateTime
等)裡面的內容,使用這個方法轉換成字串表示形式。
下面是簡易的示範例子
int num = 22;
string strNum = num .ToString();
Console.WriteLine(strNum ); // Output: "22"
可以看到,strNum 前面是string的類型,表示num加上.ToString()這個方法,會變成字串string的類型才可以被放到string strNum裡面。
換個方式看,當我們程式碼運作的時候,如果這時候滑鼠游標滑到strNum可以看到下面顯示這個(區域變數)string strNum表示有成功轉換成string的類型。
除了int可以轉換以外,還有其他幾個可以使用ToString轉換的,像是可以自訂日期時間格式
static void Main()
{
CustomDate customDate = new CustomDate { Day = 5, Month = 9, Year = 2023 };
Console.WriteLine(customDate); // Output: "09/05/2023"
}
class CustomDate
{
public int Day { get; set; }
public int Month { get; set; }
public int Year { get; set; }
public override string ToString()
{
return $"{Month:D2}/{Day:D2}/{Year}";
}
}
可以看到下圖輸出的格式也是字串的形式呈現。
上面程式碼創建了一個 CustomDate的class類別,用這個類別覆寫了 ToString的方法,以自訂日期格式呈現出雙位數的月份還有日期形式。
換成自訂集合類別的 ToString
Day 7 的時候有提到關於集合使用的方式,這裡就加上集合跟ToString來練習呈現(如果忘記.Add可以到
Day 7的集合去看)。
static void Main()
{
CustomCollection<int> collection = new CustomCollection<int>();
collection.Add(1);
collection.Add(2);
collection.Add(3);
Console.WriteLine(collection); // Output: "1, 2, 3"
}
class CustomCollection<T>
{
private List<T> items = new List<T>();
public void Add(T item)
{
items.Add(item);
}
public override string ToString()
{
return string.Join(", ", items);
}
}
錯誤訊息格式也可以自訂
static void Main()
{
CustomError error = new CustomError("This is a custom error.");
Console.WriteLine(error); // Output: "Custom Error: This is a custom error."
}
class CustomError : Exception
{
public CustomError(string message) : base(message) { }
public override string ToString()
{
return $"Custom Error: {Message}";
}
}
自訂的錯誤類別 CustomError
繼承自 Exception
,並覆寫了 ToString 方法,以自訂錯誤訊息的格式。
在前面Day4 提到使用.Parse的方法。
這上面也提到可以用ToString轉換成字串,那還有另一個轉換成整數的方法,這裡補充這個轉換成整數的另外一個方法。
ToInt32:這是一個方法,用於將某種資料型別(通常是字串或其他數值型別)轉換為整數( int )。它需要一個明確的轉換操作,因為不是所有的資料型別都能夠隱含地轉換為整數。
雖然 Convert.ToInt32 和 int.Parse 都是將字串轉換為整數的方法,但它們兩個還是有差異:
處理 null 或空字串:
Convert.ToInt32
:當傳遞 null 或空字串給 Convert.ToInt32 時,它會導致 0 的返回值,不會引發異常。int.Parse
:之前有提到當傳遞 null 或空字串給 int.Parse 時,它會引發 System.FormatException
異常。string nullString = null;
string emptyString = "";
int result1 = Convert.ToInt32(nullString); // result1 為 0
int result2 = Convert.ToInt32(emptyString); // result2 為 0
int result3 = int.Parse(nullString); // 會引發 FormatException 異常
int result4 = int.Parse(emptyString); // 會引發 FormatException 異常
處理無效格式的字串:
Convert.ToInt32
:當傳遞無效格式的字串給 Convert.ToInt32 時,它會導致 0 的返回值,不會引發異常。int.Parse
:當傳遞無效格式的字串給 int.Parse 時,它會引發 System.FormatException
異常。string invalidString = "abc";
int result1 = Convert.ToInt32(invalidString); // result1 為 0
int result2 = int.Parse(invalidString); // 會引發 FormatException 異常
第8天完成,越寫越覺得自己還有許多需要複習的地方,最初在學習的時候並沒有理解,雖然在大量練習的過程中,知道哪時候可以用甚麼,但透過撰寫的過程才真的有逐漸的理解過去不那麼明白的地方,期許可以保持這樣的學習的動力繼續完成挑戰。