5、始终为自定义的类或结构提供ToString()

      ToString()方法:是获取对象的字符串表示的一种便捷方式。为了方便用户,我们应该给自定义类重写ToString()函数,使ToString()的返回值更加贴近类对象的意义。如果不重写ToString()函数会怎样?众所周知,在.net环境下,所有的类都继承自System.Object类,如果不重写ToString()函数,自然会调用Object类的ToString()函数:

1  public   virtual   string  ToString()
2  {
3       return   this .GetType().FullName;
4  }
5 

    从代码可以看出,返回的仅仅是对象的类型名而已,对于用户来说没有多大意义。

    下面我们来看下微软是怎么做的。

    如下所示:Windows FormListBox类的ToString()函数

ContractedBlock.gif ExpandedBlockStart.gif Code
 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(040) : itemText;
12             text = text + ", Items[0]: " + text3;
13         }
14     }
15     return text;
16 }


   就像微软做的这样,我们在为自定义类重写ToString()函数时,应该考虑该类对象的实际意义和给用户的最直观的信息。

但是对于一些稍微复杂的类对象,由于它的信息比较复杂,单靠一个简单的ToString()函数是不能满足用户的需要。比如System.DateTime。由于各地的文化差异,使得有些地区之间的时间格式不一样,另外由于DateTime的信息比较复杂,不仅包括年、月、日还有分、秒、时,这时一个简单的ToString()函数是无法满足要求的。那么System.DateTime是怎么实现的?

首先介绍下面几个接口:ICustomFormatterIFormatProvider以及IFormattable
1、ICustomFormatter。定义一种方法,它支持对象值的自定义(用户定义)格式设置。它的定义如下:

1  public   interface  ICustomFormatter
2  {
3    //  Methods
4       string  Format( string  format,  object  arg, IFormatProvider formatProvider);
5  }


      Format函数中有一IFormatProvider参数,那么IFormatProvider又是怎样的?

2、IFormatProvider返回一个对象,该对象为指定类型提供格式设置服务。它的定义如下:

1  public   interface  ICustomFormatter
2  {
3    //  Methods
4       string  Format( string  format,  object  arg, IFormatProvider formatProvider);
5  }

3IFormattable提供将对象的值格式化为字符串表示形式的功能。它的定义如下:

1  public   interface  IFormattable
2  {
3       //  Methods
4       string  ToString( string  format, IFormatProvider formatProvider);
5  }


        ToString函数中也有一IFormatProvider参数。

    接口是定义规则的,现在规则知道了,那么应该怎么样使用呢?

    下面举一个简单的SimpleDateTime类加以说明。

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 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 ExpandedBlockStart.gif Code
 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)。这样,当用户需要扩展格式转换时,可以按要求实现ICustomFormatterIFormatProvider接口,就可以达到用户想要的目的了。如下所示:

ContractedBlock.gif ExpandedBlockStart.gif Code
 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函数。

转载于:https://www.cnblogs.com/JiangSoney/archive/2009/08/12/1544742.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值