这里的其他答案很重要,但让我们把它们放在一起来看看是如何String.Format
工作的。
它有五个重载,但我们只讨论它们都重定向到的一个(这不是实际代码,如果您想使用 Reflector 或 ILSpy 来查看它,您可以在 参考资料中找到它StringBuilder.AppendFormat
)。为了便于理解,这被简化了。
public static string Format(IFormatProvider provider, string format, params object[] args)
{
StringBuilder sb = new StringBuilder();
// Break up the format string into an array of tokens
Token[] tokens = ParseFormatString(format);
foreach (Token token in tokens)
{
switch (token.TokenType)
{
// A Text token is just some text to output directly
case TokenType.Text:
sb.Append(token.Text);
break;
// An Index token represents something like {0} or {2:format}
// token.Index is the argument index
// token.FormatText is the format string inside ('' in the first example, 'format' in the second example)
case TokenType.Index:
{
object arg = args[token.Index];
IFormattable formattable = arg as IFormattable;
if (formattable != null && token.FormatText.Length > 0)
{
// If the argument is IFormattable we pass it the format string specified with the index
sb.Append(formattable.ToString(token.FormatText, provider));
}
else
{
// Otherwise we just use Object.ToString
sb.Append(arg.ToString());
}
}
break;
}
}
return sb.ToString();
}
在您的问题中,您问为什么当您传递“05-22-2012”时格式字符串不被应用。正如 Guffa 所说,那不是 DateTime 对象,而是 String 对象。
正如 GSerjo 所说,字符串不是 IFormattable。字符串不可格式化,因为格式化是将某些内容转换为字符串的过程。字符串已经是字符串了!
所以你可以看到,当 Format 方法到达索引器时,arg
它不会是 IFormattable,它只会调用ToString
. 对字符串调用 ToString 只会返回自身,它已经是一个字符串。
总之,如果您的格式字符串包含带有内部格式字符串的索引(例如 {0:format}),则该内部格式字符串仅在关联的参数是IFormattable
并且它知道如何处理您的格式字符串时应用给它。