IFormattable的参考实施

时间:2013-01-08 18:13:45

标签: c# .net iformattable

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,我应该抛出一个特殊的异常吗?
  3. 欢迎任何博客文章/代码示例/ MSDN参考。

2 个答案:

答案 0 :(得分:39)

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

IFormattable

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

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

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

实施IFormattable

因此,让我们假设我们正在创建一些新的自我格式化类。如果它只知道一种格式化的方法,它应该只是覆盖object.ToString(),而不是更多。如果类知道多种格式化方法,则应实现IFormattable

format参数

the documentation IFormattable.ToString格式字符串"G"(代表一般格式)必须支持。建议null或空格式字符串等效于格式字符串"G"。确切的含义取决于我们。

formatProvider参数

如果我们需要任何特定的文化,或者因此会有所不同,我们需要使用IFormatProvider参数。我们会使用IFormatProvider.GetFormat从中请求某种类型。如果IFormatProvider为null,或者IFormatProvider.GetFormat对于我们想要的类型返回null,我们应该回退到这个变化信息的某个默认源。

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

格式化也可能涉及格式化某些子对象。在这种情况下,您可能想要传递IFormatProvider。 MSDN有excellent example实施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可以作为IFormatProviderstring.Format等方法中的StringBuilder.AppendFormat参数传递。

提供的ICustomFormatterFormat执行的每种格式调用string.Format方法。如果ICustomFormatter不熟悉所使用的格式字符串或不支持该类型,则只需委托给IFormattable.ToStringObject.ToString。如果您要格式化尚未提供格式支持的对象,ICustomFormatter documentation提供了所需内容的列表,如果您只想向现有IFormattable添加额外格式,则需要提供所需内容。它还提供了添加额外格式案例的示例。

参考

This MSDN page提供了.NET格式化系统的精彩概述,并提供了MSDN中几乎所有其他相关页面的链接。这是几乎所有与格式相关的问题的最佳起点。

答案 1 :(得分:0)

对于这些问题,可以在Mono源代码中找到一个好的信息。您可能会在其mscorlib.dll代码中找到相当多的用法。