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);
    }
}

但似乎还有其他潜在情况需要解决,即:
  • 如果formatProvider为null,我应该回到this.ToString()吗?
  • 如果formatProvider.GetFormat(typeof(ICustomFormatter))返回null,我应该抛出一个特定的异常吗?

  • 任何博客文章/代码示例/ MSDN引用均表示赞赏。

    最佳答案

    您似乎误解了.NET Framework格式设置基础结构的设计。不应在ICustomFormatter的实现内引用IFormattable.ToString,因为这与该接口(interface)的预期目的相冲突。
    IFormattable
    如果对象知道如何格式化自身,则仅应实现IFormattable(理想情况下,当然应将其委托(delegate)给另一个类,但此处将有意地进行耦合)。一个对象可能知道如何以多种不同的方式格式化自身,因此格式字符串允许您在它们之间进行选择。即使有可能仍然缺少信息,但这些信息因文化而异。因此,存在第二个参数间接提供此类信息。

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

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

    实现IFormattable
    因此,让我们想象一下我们正在创建一些新的自格式化类。如果它仅知道一种格式化自身的方法,则应仅覆盖object.ToString(),仅此而已。如果该类知道多种格式化自身的方法,则应实现IFormattable
    format参数

    对于IFormattable.ToStringthe documentation,必须支持"G"的格式字符串(代表常规格式)。建议将null或空格式字符串与"G"格式字符串等效。确切的含义取决于我们。
    formatProvider参数

    如果我们需要特定于文化的任何内容,或者可能会有所不同,则需要使用IFormatProvider参数。我们将使用IFormatProvider.GetFormat从中请求某些类型。如果IFormatProvider为null,或者IFormatProvider.GetFormat为我们想要的类型返回null,则我们应该退回到某个默认源以获取此变化的信息。

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

    格式化也可能涉及格式化某些子对象。在这种情况下,您可能希望向下传递IFormatProvider。 MSDN有一个实现IFormattableexcellent example展示了这种情况。

    其他ToString重载

    在实现IFormattable时,以与以下等效的方式重写Object.ToString()是很重要的

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

    这样做可确保somestring + yourobjectstring.Format("{0}{1}",somestring, yourobject)等价,您的用户将期望它是true。

    为了方便用户,您可能应该提供string ToString(string format)。同样,如果您的默认格式具有可以从IFormatProvider中受益的任何不同组件,则您可能还需要提供public string ToString(IFormatProvider provider)
    ICustomFormatter
    因此,如果我们要格式化一个不知道如何格式化自身的类,或者想要使用该类本身不支持的某种格式,该怎么办。这就是ICustomFormatter变得重要的地方。可以提供IFormatProvider类型的ICustomFormatter可以在IFormatProviderstring.Format之类的方法中作为StringBuilder.AppendFormat参数传递。

    提供的ICustomFormatter具有针对Format所做的每种格式调用的string.Format方法。如果ICustomFormatter不熟悉所使用的格式字符串或对该类型的格式不支持,则只需将其委派给IFormattable.ToStringObject.ToString即可。 ICustomFormatter documentation提供了一个列表,如果您正在格式化尚不提供格式支持的对象,则该列表是必需的;如果您只想向现有IFormattable添加一个额外的格式,则需要该列表。它还提供了添加额外格式案例的示例。

    引用

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

    10-02 02:34