ToString()方法:是获取对象的字符串表示的一种便捷方式。为了方便用户,我们应该给自定义类重写ToString()函数,使ToString()的返回值更加贴近类对象的意义。如果不重写ToString()函数会怎样?众所周知,在.net环境下,所有的类都继承自System.Object类,如果不重写ToString()函数,自然会调用Object类的ToString()函数:
2 {
3 return this .GetType().FullName;
4 }
5
从代码可以看出,返回的仅仅是对象的类型名而已,对于用户来说没有多大意义。
下面我们来看下微软是怎么做的。
如下所示:Windows Form的ListBox类的ToString()函数
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1 public override string ToString()
2 {
3 string text = base.ToString(); // 得到类型名
4 if (this.itemsCollection != null)
5 {
6 text = text + ", Items.Count: " + this.Items.Count.ToString();
7 if (this.Items.Count > 0)
8 {
9 string itemText = base.GetItemText(this.Items[0]);
10 string text3 =
11 (itemText.Length > 40) ? itemText.Substring(0, 40) : itemText;
12 text = text + ", Items[0]: " + text3;
13 }
14 }
15 return text;
16 }
就像微软做的这样,我们在为自定义类重写ToString()函数时,应该考虑该类对象的实际意义和给用户的最直观的信息。
但是对于一些稍微复杂的类对象,由于它的信息比较复杂,单靠一个简单的ToString()函数是不能满足用户的需要。比如System.DateTime。由于各地的文化差异,使得有些地区之间的时间格式不一样,另外由于DateTime的信息比较复杂,不仅包括年、月、日还有分、秒、时,这时一个简单的ToString()函数是无法满足要求的。那么System.DateTime是怎么实现的?
首先介绍下面几个接口:ICustomFormatter、IFormatProvider以及IFormattable
1、ICustomFormatter。定义一种方法,它支持对象值的自定义(用户定义)格式设置。它的定义如下:
2 {
3 // Methods
4 string Format( string format, object arg, IFormatProvider formatProvider);
5 }
Format函数中有一IFormatProvider参数,那么IFormatProvider又是怎样的?
2、IFormatProvider返回一个对象,该对象为指定类型提供格式设置服务。它的定义如下:
2 {
3 // Methods
4 string Format( string format, object arg, IFormatProvider formatProvider);
5 }
3、IFormattable。提供将对象的值格式化为字符串表示形式的功能。它的定义如下:
2 {
3 // Methods
4 string ToString( string format, IFormatProvider formatProvider);
5 }
ToString函数中也有一IFormatProvider参数。
接口是定义规则的,现在规则知道了,那么应该怎么样使用呢?
下面举一个简单的SimpleDateTime类加以说明。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1 public class SimpleDateTime:IFormattable
2 {
3 private readonly int _year;
4 public int Year
5 {
6 get
7 {
8 return _year;
9 }
10 }
11
12 private readonly int _month;
13 public int Month
14 {
15 get
16 {
17 return _month;
18 }
19 }
20
21 private readonly int _day;
22 public int Day
23 {
24 get
25 {
26 return _day;
27 }
28 }
29
30 public SimpleDateTime(
31 int y,
32 int m,
33 int d)
34 {
35 _year = y;
36 _month = m;
37 _day = d;
38 }
39
40 public override string ToString()
41 {
42 return ""+_year+@"/"+_month+@"/"+_day+"";
43 }
44 public string ToString(string format)
45 {
46 return ToString(format, null);
47 }
48 public string ToString(string format, IFormatProvider formatProvider)
49 {
50 if (formatProvider != null)
51 {
52 ICustomFormatter fmt = formatProvider.GetFormat(this.GetType())
53 as ICustomFormatter;
54 if (fmt != null)
55 return fmt.Format(format, this, formatProvider);
56 }
57 format = format.ToLower();
58 switch (format)
59 {
60 case "y":
61 return _year.ToString();
62 case "m":
63 return _month.ToString();
64 case "d":
65 return _day.ToString();
66 case "yyyy-mm-dd":
67 return "" + _year + "-" + _month + "-" + _day + "";
68 default:
69 return ToString();
70
71 }
72 }
73 }
如果想偷懒,认为这些格式转换已经能满足用户的需要,不需要用户利用IFormatProvider扩展格式转换了,那么SimpleDateTime自定义类完全可以不用继承接口:IFormattable,实现string ToString(string format, IFormatProvider formatProvider),只需将函数string ToString(string format)改写成如下形式就可以了。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1 public string ToString(string format)
2 {
3 switch (format)
4 {
5 case "y":
6 return _year.ToString();
7 case "m":
8 return _month.ToString();
9 case "d":
10 return _day.ToString();
11 case "yyyy-mm-dd":
12 return "" + _year + "-" + _month + "-" + _day + "";
13 default:
14 return ToString();
15 }
16 }
这样做是不负责任的。一旦不能满足用户格式转换的需要,用户就毫无办法了,所以我们还是勤快点,将自定义的类继承接口:IFormattable,实现string ToString(string format, IFormatProvider formatProvider)。这样,当用户需要扩展格式转换时,可以按要求实现ICustomFormatter和IFormatProvider接口,就可以达到用户想要的目的了。如下所示:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1 public class DateTimeFormat : ICustomFormatter
2 {
3 public string Format(string format,
4 object arg,
5 IFormatProvider formatProvider)
6 {
7 SimpleDateTime dateTime = arg as SimpleDateTime;
8 if (dateTime == null)
9 {
10 return arg.ToString();
11 }
12 return string.Format("{0}/{1}/{2}", dateTime.Day,dateTime.Month,dateTime.Year);
13 }
14 }
15 public class DateTimeFormatInfo : IFormatProvider
16 {
17 public object GetFormat(Type formatType)
18 {
19 if (formatType == typeof(SimpleDateTime))
20 {
21 return new DateTimeFormat();
22 }
23 return null;
24 }
25 }
如此:SimpleDateTime类比较灵活的实现了时间的多种格式输出,用户也可以按照要求实现各种格式输出了。由此我们可以大致了解到System.DateTime类的ToString函数是如何实现的。
总之:不管怎样,我们都要为我们自定义的类负责,为该类提供合理的ToString函数。