IFormattable和IFormatProvider用于格式化输出
,比如日期格式(2020/3/18 19:56:29、2020年3月18日)、数字格式(小数位、数值类型decimal/float/double)、其他需要规范输出的应用场景。
IFormattable 接口将对象的值格式化为字符串表示形式。
IFormatProvider 接口检索对象以控制格式化。
以IFormattable 接口的示例为例,根据摄氏度,格式化输出对应华氏度和开尔文。
格式化类型包括G(默认,摄氏度)、C(摄氏度)、F(华氏度)、K(开尔文)。
单独使用IFormattable
IFormattable 的ToString方法接受一个代表格式的字符串参数,通过对这个参数的分析来进行格式化输出。
需要格式化的类直接实现IFormattable 接口,Temperature(温度)类直接实现IFormattable接口。
public class Temperature : IFormattable { private decimal temp; public Temperature(decimal temperature) { if (temperature < -273.15m) throw new ArgumentOutOfRangeException(String.Format("{0}低于绝对零度",temperature)); this.temp = temperature; } /// /// 摄氏度 /// public decimal Celsius { get { return temp; } } /// /// 华氏温度 /// public decimal Fahrenheit { get { return temp * 9 / 5 + 32; } } /// /// 开尔文(热力学温标或称绝对温标) /// public decimal Kelvin { get { return temp + 273.15m; } } public override string ToString() { return this.ToString("G", CultureInfo.CurrentCulture); } public string ToString(string format) { return this.ToString(format, CultureInfo.CurrentCulture); } public string ToString(string format, IFormatProvider provider) { if (String.IsNullOrEmpty(format)) format = "G"; if (provider == null) provider = CultureInfo.CurrentCulture; //G(默认,摄氏度)、C(摄氏度)、F(华氏度)、K(开尔文) switch (format.ToUpperInvariant()) { case "G": case "C": return temp.ToString("F2", provider) + " °C"; case "F": return Fahrenheit.ToString("F2", provider) + " °F"; case "K": return Kelvin.ToString("F2", provider) + " K"; default: throw new FormatException(String.Format("{0}格式不被支持", format)); } } }
Temperature temp1 = new Temperature(0); //带有格式化字符串C/K/F Console.WriteLine("{0:C} (Celsius) = {0:K} (Kelvin) = {0:F} (Fahrenheit)\n", temp1); //其他写法见示例代码
使用IFormatProvider
String.Format方法接受一个IFormatProvider类型的参数,以允许类型的使用者提供格式化的方法。
public class Temperature { internal decimal temp; public Temperature(decimal temperature) { if (temperature < -273.15m) throw new ArgumentOutOfRangeException(String.Format("{0}低于绝对零度.",temperature)); this.temp = temperature; } }
单独写自定义FormatProvider类实现格式化输出,并在格式化方法中加入这个FormatProvider类对象。
public class TemperatureFormatProvider : IFormatProvider, ICustomFormatter { public string Format(string format, object arg, IFormatProvider provider) { if (arg.GetType() != typeof(Temperature)) throw new FormatException(String.Format("类型 '{0}' 是无效的.", arg.GetType().ToString())); decimal temp = (arg as Temperature).temp; if (String.IsNullOrEmpty(format)) format = "G"; if (provider == null) provider = CultureInfo.CurrentCulture; switch (format.ToUpperInvariant()) { case "G": case "C": return temp.ToString("F2", provider) + " °C"; case "F": var Fahrenheit= temp * 9 / 5 + 32; return Fahrenheit.ToString("F2", provider) + " °F"; case "K": var Kelvin= temp + 273.15m; return Kelvin.ToString("F2", provider) + " K"; default: throw new FormatException(String.Format("{0}格式不被支持.", format)); } } public object GetFormat(Type formatType) { if (formatType == typeof(ICustomFormatter)) return this; else return null; } }
Console.WriteLine(String.Format(new TemperatureFormatProvider(), "{0:C} (Celsius) = {0:K} (Kelvin) = {0:F} (Fahrenheit)\n", temp1));
示例代码
UseIFormattable
UseIFormatProvider
参考资料
IFormattable 接口
IFormatProvider 接口
.NET基础 (13)IFormattable和IformatProvider的使用