ToString() 是 .NET 最常被呼叫的方法之一。預設 Object.ToString() 僅回傳型別名稱("Customer"),毫無實用資訊。每個型別都應覆寫 ToString(),提供給開發者、除錯器、UI 控制項(ListBox、ComboBox、DataGrid)可讀的文字描述。
public class Customer
{
private string _name;
public override string ToString() => _name; // 最常用描述
}
效果:
Console.WriteLine(cust) 直接顯示名稱。String.Format("{0}", cust)、listBox.Items.Add(cust) 自動顯示名稱而非型別名。當型別有多個重要屬性(名稱、營收、電話),單一 ToString() 不夠。實作 IFormattable:
public class Customer : IFormattable
{
private string _name, _phone;
private decimal _revenue;
// 格式字元:n=名稱, r=營收, p=電話,支援組合如 "nrp"
public string ToString(string format, IFormatProvider provider)
{
if (provider != null)
{
var fmt = provider.GetFormat(GetType()) as ICustomFormatter;
if (fmt != null) return fmt.Format(format, this, provider);
}
switch (format?.ToLower())
{
case "r": return _revenue.ToString();
case "p": return _phone;
case "nr": return string.Format("{0,20}, {1,10:C}", _name, _revenue);
case "nrp": return string.Format("{0,20}, {1,10:C}, {2,15}", _name, _revenue, _phone);
case "n": case "g": case "": case null: return _name;
default: return _name;
}
}
public override string ToString() => ToString("G", null);
}
用法:
var c = new Customer(...);
Console.WriteLine($"Customer: {c:nrp}"); // 自動呼叫 IFormattable.ToString
型別作者未預見的格式需求,呼叫端可自行實作:
public class CustomerFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type t) => t == typeof(ICustomFormatter) ? this : null;
public string Format(string fmt, object arg, IFormatProvider prov)
{
if (arg is Customer c)
return string.Format("{0,50}, {1,15}, {2,10:C}", c.Name, c.Phone, c.Revenue);
return arg.ToString();
}
}
// 使用:
Console.WriteLine(string.Format(new CustomerFormatter(), "{0}", customer));
"G"、""、null 三種格式,回傳與 ToString() 相同結果。最小成本,最大回報:覆寫 ToString() 讓型別在除錯、日誌、UI、序列化皆友善。複雜型別加上 IFormattable,極端情況呼叫端可用 IFormatProvider 自行擴充。別讓使用者看到 "MyNamespace.Customer"。