//获取对象的字符串表示:将一个对象格式化成字符串。
//FCL的设计者提出了一个统一范式。可以调用ToString方法来获取任何对象的字符串表示。
//每个类型都有责任提供相应的代码来将一个实例的值转换成字符串。
//public、virtual、无参数的ToString()方法:
//1)使用默任的“G”格式
//2)使用默任的当前线程文化
//3)通常调用ToString(null,null)
//任何类型如果希望提供一个合理的方式来获取对象当前值的字符串表示,都应该重写ToString()方法。
//FCL内建的所有基类型(Int32,Double,Decimal,DateTime等)都重写了它们的ToString()方法。
//问题:
//1)调用者无法控制字符串的格式。
//2)调用者不能选择一种特定的语言文化来格式化一个字符串。
//类型实现System.IFormattable接口,调用者就能够选择精确的格式和语言文化。
//FCL内建的所有基类型(Int32,Double,Decimal,DateTime等)都实现了System.IFormattable接口
//每个枚举类型定义都将自动实现System.IFormattable接口,以便根据枚举类型的一个实例来获取一个有意义的字符串。
//
//System.IFormattable接口的ToString方法:使用指定的格式和文化格式化当前实例的值。
//string ToString ( string format, IFormatProvider formatProvider)
//format(格式):指定要使用的格式,告诉方法应该如何格式化对象。
// 空引用,表示使用为 IFormattable 实现的类型定义的默认格式(“G”格式)。
// 默认格式:实现一个类型时,自己认为最常用的一种格式。
//formatProvider(格式提供者):它引用实现了用于格式化该值的System. IFormatProvider接口的一个类型的实例。
// 为ToString方法提供了具体的语言文化信息。
// 空引用,使用与当前调用线程关联的语言文化信息。
//
//负责实现“System.IFormatProvider接口的ToString方法”的类型要决定哪些格式字符串能够被识别。
//假如传递的格式字符串无法被类型识别,类型应该抛出一个System.FormatException异常。
// IFormatProvider接口的基本思路是:假如一个类型实现了该接口,就认为类型的一个实例能够提供依赖于语言文化的格式化信息,
// 而与当前调用线程关联的语言文化信息应被抛弃。提供用于检索控制格式化的对象的机制。
//Object GetFormat (Type formatType)
//GetFormat方法,以获得(1)提供格式信息的格式化对象或(2)实现类型处理的对象。
// 如果格式说明符的含义因区域性而异,则格式化对象提供字符串表示形式中所用的实际字符。
//GetFormat方法 的参数 formatType 能够识别任何类型,允许请求任何类型的格式化信息。
// 在.NET中,类型在调用时,暂时只会请求数字或日期/时间信息。
//
//在FCL中,只有三个类型NumberFormatInfo、DateTimeFormatInfo 和 CultureInfo 实现 IFormatProvider 接口。
//NumberFormatInfo 提供数字格式信息,如用于小数分隔符和千位分隔符的字符,以及货币值中货币符号的拼写和位置。
//DateTimeFormatInfo 提供与日期相关和与时间相关的格式信息,如日期模式中月、日和年的位置。
//CultureInfo 包含特定区域性中的默认格式信息,其中包括数字格式信息以及与日期相关和与时间相关的格式信息。
//
//在一个NumberFormatInfo对象实例上调用GetFormat(typeof(NumberFormatInfo))方法时,该方法会核实被请求的类型是不是NumberFormatInfo。
// 如果是,就返回this;否则,返回null。
//在一个DateTimeFormatInfo对象实例上调用GetFormat(typeof(DateTimeFormatInfo))方法时,该方法会核实被请求的类型是不是DateTimeFormatInfo。
// 如果是,就返回this;否则,返回null。
//这两个类实现IFormatProvider 接口,纯粹是为了简化编程。
//ToString方法格式化数字(Int32,Double,Decimal等)
//1)如果 formatProvider == null,则
// formatProvider = System.ThreadingThread.CurrentThread.CurrentCulture
// 获得System.Globalization.CultureInfo 类型的一个与当前调用线程关联的提供格式信息的格式化对象
//2)如果 formatProvider <> null,则
// NumberFormatInfo nfi = (NumberFormatInfo)formatProvider.GetFormat(typeof(NumberFormatInfo));
// 返回NumberFormatInfo类型的格式化对象nfi
//3)如果 format = null,则
// format = "G"
//4)在构造并格式化一个字符串的时候,读取格式化对象nfi的属性,获取恰当的数字格式化信息。
// 如果格式说明符的含义因区域性而异,则格式化对象提供字符串表示形式中所用的实际字符。
//ToString方法格式化日期/时间(DateTime)
//1)如果 formatProvider == null,则
// formatProvider = System.ThreadingThread.CurrentThread.CurrentCulture
// 获得System.Globalization.CultureInfo 类型的一个与当前调用线程关联的提供格式信息的格式化对象
//2)如果 formatProvider <> null,则
// DateTimeFormatInfo dtfi = (DateTimeFormatInfo)formatProvider.GetFormat(typeof(DateTimeFormatInfo));
// 返回DateTimeFormatInfo类型的格式化对象dtfi
//3)如果 format = null,则
// format = "G"
//4)在构造并格式化一个字符串的时候,读取格式化对象dtfi的属性,获取恰当的日期/时间格式化信息。
// 如果格式说明符的含义因区域性而异,则格式化对象提供字符串表示形式中所用的实际字符。
//Decimal类型提供了四个不同的ToString方法
//1)public override ToString();//调用ToString(null,null)
//2)public String ToString ( string format, IFormatProvider formatProvider);
//3)public String ToString ( string format);//调用ToString(format,null)
//4)public String ToString ( IFormatProvider formatProvider);//调用ToString(null,formatProvider)
//客户端通常使用当前线程的语言文化信息来格式化一个字符串。
//服务器端使用不变的文化(System.Globalization.CultureInfo的静态属性 InvariantCulture)来格式化一个字符串,
// 并将其保存在一个数据文件中,以便将来对其进行解析。
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
class Point : IFormattable
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public override String ToString() { return ToString(null, null); }
public String ToString(String format, IFormatProvider fp)
{
// If no format is passed, display like this: (x, y).
if (format == null) return String.Format("({0}, {1})", x, y);
// For "x" formatting, return just the x value as a string
if (format == "x") return x.ToString();
// For "y" formatting, return just the y value as a string
if (format == "y") return y.ToString();
// For any unrecognized format, throw an exception.
throw new FormatException(String.Format("Invalid format string: '{0}'.", format));
}
}
public sealed class App
{
static void Main()
{
//Culture
Decimal price = 123.54M;
//越南文化
String s = price.ToString("C", new CultureInfo("vi-VN"));
Console.WriteLine(s);
//不变文化
s = price.ToString("C", CultureInfo.InvariantCulture);
Console.WriteLine(s);
// Create the object.
Point p = new Point(5, 98);
// Test ToString with no formatting.
Console.WriteLine("This is my point: " + p.ToString());
// Use custom formatting style "x"
Console.WriteLine("The point's x value is {0:x}", p);
// Use custom formatting style "y"
Console.WriteLine("The point's y value is {0:y}", p);
try
{
// Use an invalid format; FormatException should be thrown here.
Console.WriteLine("Invalid way to format a point: {0:XYZ}", p);
}
catch (FormatException e)
{
Console.WriteLine("The last line could not be displayed: {0}", e.Message);
}
}
}
// This code produces the following output.
//
// This is my point: (5, 98)
// The point's x value is 5
// The point's y value is 98
// The last line could not be displayed: Invalid format string: 'XYZ'.