【问题标题】:Why is `GetFormat` called twice?为什么`GetFormat`被调用了两次?
【发布时间】:2018-05-18 00:18:25
【问题描述】:

我有一个IFormatProvider,它会注销它传递的类型:

internal class LoggingFormatProvider : IFormatProvider
{
    public object GetFormat(Type formatType)
    {
        WriteLine($"  formatType: {formatType.FullName}");
        return null;
    }
}

当我用这段代码调用它时:

var myLoggingProvider = new LoggingFormatProvider();
string.Format(myLoggingProvider, "123: {0}", 123);

它输出两个对GetFormat方法的调用:

formatType: System.ICustomFormatter
formatType: System.Globalization.NumberFormatInfo

为什么会有两个调用?

当涉及到格式化类型时,我通常对什么叫做什么和什么感到非常困惑。

【问题讨论】:

  • 您缺少一个步骤,您还需要提供 ICustomFormatter 的实现,其 Format() 方法可以完成实际工作。它要求你提供它,但你决定不给它。所以它一直在寻找,回到标准提供者。我猜您希望您的 LoggingFormatProvider 类实现 ICustomFormatter。然后,您只需从 GetFormat() 中返回 this
  • @HansPassant 返回null 是否意味着使用默认值重试
  • 大概,是的。当您表示要提供自定义格式化程序时,返回 null 并没有多大意义。但是,如果您出于某种原因不希望它是自定义的,那么您可以同意标准格式化程序。
  • @HansPassant 123.ToString(myLoggingProvider) 只打一个电话(NumberFormatInfo)很奇怪吗?

标签: c# .net


【解决方案1】:

当您调用string.Format(myLoggingProvider, "123: {0}", 123) 时,.NET 首先询问您的LoggingFormatProvider 实例是否可以提供自定义格式化程序(即ICustomFormatter 的实例)。因为它不能(你返回null),并且要格式化的值是一个数字,所以它回退到请求你一个NumberFormatInfo的实例。

如果您的参数是DateTime 的一个实例,您将收到一个DateTimeFormatInfo 实例的请求。正如the documentation for IFormatProvider 所暗示的那样,数字和日期显然是您将获得这种回退的唯一参数类型。

【讨论】:

  • 我想从源代码 referencesource.microsoft.com/#mscorlib/system/text/… 特别是从第 1440 行添加它,我们可以看到它使用默认格式化程序,以防类型是 IFormattable 并且自定义提供程序无法提供指定类型的格式化程序
  • 我想知道这是不是像这样的默认魔法。感谢您的确认。
猜你喜欢
  • 2013-11-20
  • 2019-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-08
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多