C#:IFormattable、IFormatProvider 和 ICustomFormatter 之间的连接,以及何时使用什么

标签 c# formatting

IFormattableIFormatProviderICustomFormatter有什么区别和联系,什么时候用?一个简单的实现示例也会非常好。

我并不是说什么时候在 .net 框架中使用它,而是什么时候我自己实现这些,在这种情况下,什么类通常会实现什么接口(interface)以及如何正确地实现它。

最佳答案

  • IFormattable是支持string.Format格式的对象,即{0:xxx中的xxx }。如果对象支持接口(interface),string.Format 将委托(delegate)给对象的 IFormattable.ToString 方法。

  • IFormatProvider 是格式化程序用于特定文化的日期和货币布局等配置信息的来源。

  • 但是,对于例如DateTime,您要格式化的实例已经实现 IFormattable 但您不控制实现(DateTime 在 BCL 中提供,您不能轻易替换),有一种机制可以防止 string.Format 简单地使用 IFormattable.ToString。相反,您实现 IFormatProvider,当被要求提供 ICustomFormatter 实现时,返回一个。 string.Format 在委托(delegate)给对象的 IFormattable.Format 之前检查提供程序的 ICustomFormatter,这反过来可能会询问 IFormatProvider 用于特定于文化的数据,例如 CultureInfo

这是一个程序,它显示了 string.FormatIFormatProvider 请求什么,以及控制流程是如何进行的:

using System;
using System.Globalization;

class MyCustomObject : IFormattable
{
    public string ToString(string format, IFormatProvider provider)
    {
        Console.WriteLine("ToString(\"{0}\", provider) called", format);
        return "arbitrary value";
    }
}

class MyFormatProvider : IFormatProvider
{
    public object GetFormat(Type formatType)
    {
        Console.WriteLine("Asked for {0}", formatType);
        return CultureInfo.CurrentCulture.GetFormat(formatType);
    }
}

class App
{
    static void Main()
    {
        Console.WriteLine(
            string.Format(new MyFormatProvider(), "{0:foobar}", 
                new MyCustomObject()));
    }
}

它打印这个:

Asked for System.ICustomFormatter
ToString("foobar", provider) called
arbitrary value

如果格式提供程序更改为返回自定义格式化程序,它将接管:

class MyFormatProvider : IFormatProvider
{
    public object GetFormat(Type formatType)
    {
        Console.WriteLine("Asked for {0}", formatType);
        if (formatType == typeof(ICustomFormatter))
            return new MyCustomFormatter();
        return CultureInfo.CurrentCulture.GetFormat(formatType);
    }
}

class MyCustomFormatter : ICustomFormatter
{
    public string Format(string format, object arg, IFormatProvider provider)
    {
        return string.Format("(format was \"{0}\")", format);
    }
}

运行时:

Asked for System.ICustomFormatter
(format was "foobar")

关于C#:IFormattable、IFormatProvider 和 ICustomFormatter 之间的连接,以及何时使用什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1697470/

相关文章:

c# - 如何检测当前按下的键?

java - UnityPlayerActivity全局初始化

c# - XmlSerializer 和 xsi : deserialization

c# - 在 Unity 中读取串口 "COM3"。连接建立成功,但未调用 DataReceived Handler

javascript - 并非所有浏览器都支持 toLocaleString()?

java - 在 Textview 中以千位分隔符和小数格式显示数字

c# - Linux 上托管的 Visual Studio 远程调试应用程序 - 无法枚举特定进程中 CoreCLR 的运行实例

c# - 基于 XAML 中对象属性的数值中的货币符号

algorithm - 使用格式化和未格式化的电话号码匹配用户(来自联系人,国际)

C# 组合框未正确从列表中填充