《Effective C#》读书笔记——条目5:为类型提供ToString()方法<C#语言习惯>
ToString()方法作为.NET环境中最常用的方法之一,我们应该为类型的所有者提供一个合理的ToString()版本,类型的字符串表示可用来在不同的环境下向用户轻松显示对象的相关信息;此外,类型的字符串表示还可以拥有调试环境。因此,我们创建的每一个类型都应该能覆写Object类的ToString()方法。如果创建的是更负责的类型,那么还应该实现更加完备的IFormattable.ToString()方法。
System.Ojbetc默认提供的ToString()方法会返回类型的完整名称。就像:"System.Drawing.Rect"、"System.Data.Common.DbConnection",这一般没什么用处,也不适合直接显示给用户。所以我们只需要重写一次,即可一劳永逸。
通过一个示例我们来学习如何为一个类型提供一个容易理解的,文本方式的表示。例如我们有一个包含三个字段的Customer类:
1 class Customer 2 { 3 /// <summary> 4 /// 姓名 5 /// </summary> 6 public string Name 7 { 8 get; 9 set; 10 } 11 12 /// <summary> 13 /// 收入 14 /// </summary> 15 public decimal Revenue 16 { 17 get; 18 set; 19 } 20 21 /// <summary> 22 /// 联系电话 23 /// </summary> 24 public string ContactPhone 25 { 26 get; 27 set; 28 } 29 30 /// <summary> 31 /// 覆写ToString方法,提供该类型更易理解的文本表示方式 32 /// </summary> 33 /// <returns></returns> 34 public override string ToString() 35 { 36 return Name; 37 } 38 }
对于Customer类来说,返回它的Name是一个不错的选择。在提供了Customer类的ToString()覆写之后,该类的对象即可更容易的添加到WPF控件、Silverlight控件、Web Forms控件或者被打印输出。.NET BCL(.NET Framework 基础类库)在将对象显示到如组合框、列表框、文本框或其他控件上时使用Object.ToString()的覆写版本。
提示:
在C#3.0中,编译器会为所以匿名类型创建一个默认的ToString()方法。该默认方法将显示对象中的每个属性值。
例如我们运行控制台程序:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 int[] list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 6 var test = new { Name = "me", Numbes = from li in list select 1 }; 7 8 Console.WriteLine(test); 9 Console.Read(); 10 } 11 }
运行程序:
实现IFormattable接口
虽然简单的ToString()方法很多时候已经可以满足用户自定义类型显示文本信息的需求,但有时还需要提供更强的方法。在前面的Customer类的ToString()方法中我们只是简单的返回了它的Name这个字段。如果我们想要拥有更加详细的返回,我们可以通过覆写IFormattable接口来解决这个不足。该接口包含了一个重载的ToString()方法,它允许我们为类型提供特定的格式信息。当你需要为类型输出不同形式的字符串时,这个接口即可大显身手。在下面的例子中我们可以使用特定的字符串来表示某种格式的信息,如n来表示名称等:
1 public class Customer : IFormattable 2 { 3 //属性字段省略... 4 5 public string ToString(string format, IFormatProvider formatProvider) 6 { 7 if (formatProvider != null) 8 { 9 ICustomFormatter fmt = formatProvider.GetFormat(this.GetType()) as ICustomFormatter; 10 if (fmt != null) 11 return fmt.Format(format, this, formatProvider); 12 } 13 switch (format) 14 { 15 case "r": 16 return Revenue.ToString(); 17 case "p": 18 return ContactPhone; 19 case "nr": 20 return string.Format("{0,20},{1,10:C}", Name, Revenue); 21 case "np": 22 return string.Format("{0,15},{1,10:C}", Name, ContactPhone); 23 case "n": 24 case "G": 25 default: 26 return Name; 27 } 28 } 29 }
Customer使用者即可自定义其想要输出的格式:
1 IFormattable c1 = new Customer(); 2 Console.WriteLine("Customer record:{0}", c1.ToString("nr", null));
首先我们必须支持表示通用格式的"G";其次我们必须支持两种格式的空格式,即" "和null。这三种格式返回字符串都必须和Ojbect.ToString()的覆写版本的字符串相同。实现了IFormattable接口的类型,.NET BCL都会调用IFormattable()而不是Object.ToString()。
IFormatProvider接口
IFormattable.ToString()方法的第二个参数是一个实现IFormatProvider接口的对象,该对象允许客户端提供一些我们无法事先预料的格式化选项。更详细的说明参见:IFormatProvider接口
小节:
人们总是要通过某种方式获取到类型的信息,而字符串的表示则是最通俗易懂的。因此,我们应该覆写所以类型中的ToString()方法,让其简单明了的输出对象的摘要信息。
阅读书目:《Effective C#》
扩展阅读: