ToString 的几个思考 FormatProvider
来源:互联网 发布:女友胸大什么感觉知乎 编辑:程序博客网 时间:2024/06/05 01:18
为什么要ToString
我们知道对象实例(instance)都是生存在内存的一个二进制字节。但如果我们需要将该对象实例显示出来(例如显示在控件中),那么就需要一个途径能够把对象实例转换为字符串。
3. 最简单的ToString重写
我们从上面的图片就可以看到,ToString是一个虚方法(virtual).也就代表了任何类型都可以重写该方法。不重写之前,它返回什么呢?
class Program
{
static void Main(string[] args)
{
Customer c1 = new Customer() { CustomerName = "chenxizhang", Id = 1 };
Console.Write(c1.ToString());
Console.Read();
}
}
class Customer
{
public string CustomerName { get; set; }
public int Id { get; set; }
}
我们可以看到如下的结果
也就是说,默认是将类型的完整名字输出为ToString的结果。我们可以通过反射工具看一下object这个类型的代码就很明白了
但是,很显然,如果每个类型都这么输出,那么其实对用户来说一点都不友好,或者说没有任何作用。那么该如何改变这种行为呢?答案就是可以为我们的类型重写ToString方法
class Customer
{
public string CustomerName { get; set; }
public int Id { get; set; }
public override string ToString()
{
return string.Format("Id={0},Name={1}", Id, CustomerName);
}
}
加上这个代码之后,重新执行程序就可以看到如下的效果
看起来很酷,不是吗
但是这样会有一个问题,就是说这样是不是只能有一个方法?也就是说只有一个可能性呢?如果我们想根据用户的一个选项来决定怎么输出,那么该怎么办呢?
例如,用户代码可能希望只显示CustomerName,我们该怎么办?我们很自然会想到是不是再写一个重载的方法
public string ToString(string format)
{
if (format == "NameOnly")
return CustomerName;
return ToString();
}
然后,在客户代码中就可以这样调用
Console.WriteLine(c1.ToString("NameOnly"));
这样就和谐了。
等等,事实上,是否真的要这么写呢?其实不然,.NET内置了很多所谓公用的合约(Contract),例如我们的类型要支持自定义格式化,那么就可以通过实现一个接口来完成。
class Customer:IFormattable
{
public string CustomerName { get; set; }
public int Id { get; set; }
public override string ToString()
{
return string.Format("Id={0},Name={1}", Id, CustomerName);
}
//public string ToString(string format)
//{
// if (format == "NameOnly")
// return CustomerName;
// return ToString();
//}
#region IFormattable 成员
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == "NameOnly")
return CustomerName;
return ToString();
}
#endregion
}
然后,可能需要稍微修改一下调用的代码
static void Main(string[] args)
{
Customer c1 = new Customer() { CustomerName = "chenxizhang", Id = 1 };
Console.WriteLine(c1.ToString());
Console.WriteLine(c1.ToString("NameOnly",null));
Console.Read();
}
经过这样修改之后,输出的结果是一样的。但使用接口的方式肯定更加规范,也更加推荐
但你可能会有一个疑问,这个ToString方法的第二个参数是什么东东呢?这就是下一节要讲的内容:定制的格式
大家也可以再想一下,我们现在是提供了两种可能性,但如果以后又要提供其他的可能性,是不是还要回过去修改Customer这个类型呢?目前而言,是的。但这样做显然是不够灵活的。有什么办法将这个紧耦合解开吗?
4. 定制的格式化提供程序(FormatProvider)
我们可以通过提供者模式来解决该问题。 可以编写下面这样一个类型
class CustomerFormatProvider : IFormatProvider,ICustomFormatter
{
#region IFormatProvider 成员
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
#endregion
#region ICustomFormatter 成员
public string Format(string format, object arg, IFormatProvider formatProvider)
{
Customer c = arg as Customer;
if (arg != null)
{
if (format == "NameOnly")
return c.CustomerName;
}
return c.ToString();
}
#endregion
}
然后,我们一次性修改好Customer类型里面的那个ToString方法
#region IFormattable 成员
public string ToString(string format, IFormatProvider formatProvider)
{
ICustomFormatter formatter = formatProvider.GetFormat(typeof(ICustomFormatter)) as ICustomFormatter;
if (formatter != null)
{
return formatter.Format(format, this, formatProvider);
}
return ToString();
}
#endregion
然后,在客户代码中大致要这样调用
Console.WriteLine(c1.ToString("NameOnly", new CustomerFormatProvider()));
一点都不奇怪,主程序显示的效果仍然是一样的。但是这样就是一个比较好的设计。换而言之,如果以后我们要添加一个新的格式化规则,那么我们可以单独写一个Provider,然后再调用的时候指定即可。
- ToString 的几个思考 FormatProvider
- ToString 的几个思考
- CSS的几个思考
- 几个值得思考的问题
- 几个值得思考的问题
- 网络游戏几个发展方向的思考
- 关于 Benchmark 的几个思考
- 下一代防火墙的几个思考
- GetMemory 引起的几个思考
- c# 数值类型.tostring的几个调用方式
- 几个思考
- 有关对称密码的几个思考
- 几个小例子引发的思考
- 思考C语言变量的几个“属性”
- c#几个小例子引发的思考
- 关于成为架构师的几个思考?
- String.valueOf(l)方法引发的关于2String、String.valueOf、toString区别的思考
- 正在思考的几个管理方面的几个问题
- JS-Demo2:JavaScript版TableGrid,表格头、分页表格冻结,表格头可拉动
- tcpdump用法详解
- TCP/IP协议问题透析
- Myeclipse 快捷键大全(绝对全)
- Nginx代理与负载均衡配置与优化
- ToString 的几个思考 FormatProvider
- SWT GridLayout 网格布局
- iPhone的Push(推送通知)功能原理浅析
- ulteo开源的桌面虚拟化产品
- 文本滚动元素 marquee 研究报告
- J2EE的体系结构和MVC设计模式
- wxWidgets
- Error 1606 Could Not Access Network Location %SystemDrive%/inetpub/wwwroot/ 的错误解决方法
- FRAM技术真的有可能替代flash而一统江山吗?