好奇...... 所以,如果我将日期的字符串版本转换为DateTime对象并将其传递给String.Format()方法,那么我会得到所有结果。
String.Format("The date is {0:MMMM dd, yyyy}", DateTime.Parse("05-22-2012"));
“日期是2012年5月22日”
但为什么这不起作用?
String.Format("The date is {0:MMMM dd, yyyy}", "05-22-2012")
“日期是2012年5月22日”
很抱歉,如果这是一个愚蠢的问题,但我只是想了解这是如何工作的。 感谢
答案 0 :(得分:3)
这里的其他答案点击了重点,但让我们把它们放在一起检查String.Format
的工作原理。
它有五个重载,但我们只讨论它们都重定向到的那个(这不是实际代码,如果你想用Reflector或ILSpy看到它,你会在{{{ 1}})。这是为了便于理解而简化。
StringBuilder.AppendFormat
在你的问题中,你问为什么在你通过“05-22-2012”时没有应用格式字符串。正如Guffa所说,那不是DateTime对象,它是一个String对象。
正如GSerjo所说,String不是IFormattable。字符串不是可格式化的,因为格式化是将某些内容转换为字符串的过程。字符串已经是一个字符串了!
因此,您可以看到,当Format方法转到索引器时,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();
}
将不会是IFormattable,它只会调用arg
。在字符串上调用ToString只是返回它自己,它已经是一个字符串。
总之,如果您的格式字符串包含带有内部格式字符串的索引(例如{0:format}),那么仅当关联的参数为ToString
并且它知道时才会应用该内部格式字符串如何处理你给它的格式字符串。
答案 1 :(得分:2)
自定义日期时间格式仅适用于DateTime
值。如果您使用的是字符串,则格式将被忽略,因为只有一种方法可以输出字符串。
答案 2 :(得分:2)
因为“05-22-2012”不是IFormattable
,DateTime.Parse("05-22-2012")
所以DateTime
请在此处查看更多示例