13

IFormattable是否有一个很好的参考实现?我计划为我的对象至少有一个自定义IFormatProvider,并且我想确保对于传递给IFormattable.ToString(string, IFormatProvider).

到目前为止我所拥有的:

public class MyDataClass : IFormattable
{
    /// <seealso cref="IFormattable.ToString(string, IFormatProvider)"/>
    public string ToString(string format, IFormatProvider formatProvider)
    {
        ICustomFormatter formatter = (ICustomFormatter)formatProvider.GetFormat(typeof(ICustomFormatter));
        return formatter.Format(format, this, formatProvider);
    }
}

但似乎还有其他潜在的情况应该包括在内,即:

  1. 如果formatProvider为空,我应该回退到this.ToString()吗?
  2. 如果formatProvider.GetFormat(typeof(ICustomFormatter))返回null,我应该抛出一个特殊的异常吗?

任何博客文章/代码示例/MSDN 参考都表示赞赏。

4

2 回答 2

41

您似乎误解了 .NET Framework 格式化基础结构的设计。ICustomFormatter永远不应在 的实现中引用IFormattable.ToString,因为这与该接口的预期目的相冲突。

IFormattable

一个对象只有IFormattable在知道如何格式化自己的情况下才应该实现(理想情况下,它当然应该将其委托给另一个类,但这里会有故意的耦合)。一个对象可能知道如何以多种不同的方式格式化自己,因此格式字符串允许您在它们之间进行选择。即使这样,仍然可能缺少信息,这些信息因文化而异。因此,有第二个参数可以间接提供此类信息。

传递给的类型IFormatProvider.GetFormat旨在成为特定IFormatProvider于提供给的类的类型或接口。

例如,内置数字类型希望能够检索 的实例System.Globalization.NumberFormatInfo,而DateTime相关类希望能够检索System.Globalization.DateTimeFormatInfo.

实施IFormattable

所以让我们想象我们正在创建一些新的自格式化类。如果它只知道一种格式化自己的方法,它应该简单地覆盖object.ToString(),仅此而已。如果该类知道不止一种格式化自身的方法,则应该实现IFormattable.

format参数_

根据格式字符串(代表通用格式)的文档必须支持。建议 null 或空格式字符串等效于. 确切的含义取决于我们。IFormattable.ToString"G""G"

formatProvider参数_

如果我们需要任何特定于文化的东西,或者会有所不同,我们需要使用该IFormatProvider参数。我们会使用IFormatProvider.GetFormat. 如果IFormatProvider为空,或者如果IFormatProvider.GetFormat我们想要的类型返回空,我们应该回退到这个变化信息的一些默认源。

默认源不必是静态的。可以想象,默认来源可能是应用程序中的用户设置,并且formatProvider用于预览选项更改和/或序列化需要固定格式时。

格式化也可能涉及格式化某些子对象。在这种情况下,您可能想要传递IFormatProvider下去。MSDN 有一个很好的实现示例IFormattable,说明了这种情况。

其他ToString重载

在实现时,以等同于以下方式的方式被覆盖IFormattable是很重要的Object.ToString()

public override string ToString()
{
    return this.ToString(null, System.Globalization.CultureInfo.CurrentCulture);
}

这样做可以确保它somestring + yourobject等同于string.Format("{0}{1}",somestring, yourobject),您的用户期望它是正确的。

为了方便您的用户,您可能应该提供string ToString(string format). 此外,如果您的默认格式有任何可以从中受益的不同组件IFormatProvider,您可能还需要提供public string ToString(IFormatProvider provider).

ICustomFormatter

那么如果我们想格式化一个不知道如何格式化自己的类,或者我们想使用一些类本身不支持的格式,我们该怎么办。这就是 ICustomFormatter 变得相关的地方。可以IFormatProvider提供ICustomFormatter类型的 可以作为 和 等方法中的参数IFormatProvider传递。string.FormatStringBuilder.AppendFormat

提供的每个格式都调用了ICustomFormatter它的方法。如果不熟悉使用的格式字符串或不支持该类型,则它只是委托给or 。如果您正在格式化尚未提供格式化支持的对象,该文档提供了所需内容的列表,以及如果您只想向现有的. 它还提供了添加额外格式案例的示例。Formatstring.FormatICustomFormatterIFormattable.ToStringObject.ToStringICustomFormatterIFormattable

参考

这个 MSDN 页面提供了 .NET 格式化系统的一个很好的概述,并提供了指向 MSDN 中几乎所有其他相关页面的链接。这是几乎所有与格式相关的问题的最佳起点。

于 2013-01-10T23:10:06.560 回答
0

对于此类问题,可以在Mono源代码中找到很好的信息来源。您可能会在它的mscorlib.dll代码中找到很多这样的用法。

于 2013-01-08T18:17:19.920 回答