String可能是使用最多的類型,ToString()則應該是大家使用得最多的方法了。然而它不應該僅僅是用來輸出類型的名稱,如果使用得當,它可以方便地輸出我們對類型自定義的格式。本文將循序漸進地討論ToString(),以及相關的IFormattable、IFormatProvider以及ICustomFormatter接口。
String是人們直接就可以看懂的數據類型之一,很多情況下我們都會期望能夠獲得類型的一個字符串輸出。因此,Microsoft 在.Net Framework所有類型的基類System.Object中提供了一個虛擬的 ToString()方法,它的默認實現是返回對象的類型名稱。
假設我們有這樣的一個類型,它定義了“朋友”這一對象的一些信息:
namespace CustomToString
public class Friend {
private string familyName; // 姓
private string firstName; // 名
public Friend(string familyName, string firstName){
this.familyName = familyName;
this.firstName = firstName;
}
public Friend(): this("張","子陽"){}
public string FamilyName {
get { return familyName; }
}
public string FirstName {
get { return firstName; }
}
}
}
當我們在Friend的實例上調用 ToString()方法時,便會返回類型的名稱:CustomToString.Friend。
Friend f = new Friend();
Console.WriteLine(f.ToString()); // 輸出:CustomToString.Friend
在上面的例子中,不管類型實例(對象)所包含的數據(字段值)是什麼,它總是會返回相同的結果(CustomToString.Friend)。很多時候,返回一個對象的類型名稱對我們來說沒有多大的意義,拿上面來說,我們可能更加期望能夠返回朋友的姓名(famliyName和firstName字段的值)。這時候,我們可以簡單地覆蓋System.Object基類的ToString()方法,在 Friend 類中添加如下方法:
// 覆蓋System.Object基類的 ToString() 方法
public override string ToString() {
return String.Format("Friend: {0}{1}", familyName, firstName);
}
此時,我們再次運行代碼:
Friend f = new Friend();
Console.WriteLine(f.ToString()); // 輸出:Friend: 張子陽
f = new Friend("王","濤");
Console.WriteLine(f.ToString()); // 輸出:Friend: 王濤
可以看到對於不同的對象,ToString()根據對象的字段值返回了不同的結果,這樣對我們來說會更加有意義。
有時候,我們可能需要將對象按照不同的方式進行格式化。就拿Friend類型來說:西方人是名在前,姓在後;而中國人是 姓在前,名在後。所以如果運行下面的代碼,雖然程序不會出錯,但從英語語法角度來看卻有問題:
Friend a = new Friend("Zhang", "Jimmy");
Console.WriteLine(a.ToString()); // 輸出:Friend: ZhangJimmy
而我們期望輸出的是:Jimmy Zhang。這個時候,大家可以想一想想 .Net Framework 解決這個問題采用的方法:重載ToString()。讓ToString()方法接收一個參數,根據這個參數來進行格式化。比如 int a = 123; Console.WriteLine(a.ToString("c"));指定了字符串"c"作為參數,產生貨幣類型的輸出:¥123.00。我們也可以使用這種方式來改進Friend類,在Friend中重載一個 ToString() 方法,使之根據一個字符參數來定義其字符串格式化:
// 根據字符串參數來定義類型的格式化
public string ToString(string format) {
switch (format.ToUpper()) {
case "W": // West: 西方
return String.Format("Friend : {0} {1}", firstName, familyName);
case "E": // East: 東方
return this.ToString();
case "G": // General
default:
return base.ToString();
}
}
然後我們在使用ToString()方法時可以使用重載的版本,對於英文名,我們傳入"W"作為參數,這樣就解決了上面的問題:
Friend f = new Friend();
Console.WriteLine(f.ToString()); // 輸出:Friend: 張子陽
f = new Friend("Zhang", "Jimmy");
Console.WriteLine(f.ToString("W")); // 輸出:Friend: Jimmy Zhang
NOTE:這個問題更好的解決辦法並非是重載ToString(),可以簡單地使用屬性來完成,比如這樣:
public string WesternFullNa