当我使用自定义格式化程序并将{{{0:,;'{{0}}'}}}
传递给String.Format
时,它会通过格式化程序,;'{{0}}'}
为什么会有一个尾随支架?这是我的问题还是String.Format
?
我写了一个加入IEnumerables的IFormatProvider / ICustomFormatter。它将传递的格式字符串(一次)拆分为';'并使用第一部分作为连接字符串,第二部分作为元素的格式字符串。例如,
{0:,;'{{0}}'}
会导致格式化程序被传递,;'{0}'
,它将分别作为连接和元素格式字符串分为,
和'{0}'
。然后它会返回
String.Join(",", arr.Select((elem, index) => String.Format("'{0}'", elem, index))
当我使用
时({0:,;'{{0}}'})
作为我的格式字符串,我得到了
('elem0','elem1', ... )
正如我所料,仅当我尝试使用大括号而不是括号时才会出现此错误。
适用于LINQPad的代码:
void Main()
{
// works
String.Format(new JoinFormatter(), "({0:, ;'{{0}}'})", (object)new[] { "a", "b", "c" }).Dump();
// doesn't work
String.Format(new JoinFormatter(), "{{{0:, ;'{{0}}'}}})", (object)new[] { "a", "b", "c" }).Dump();
}
public class JoinFormatter : IFormatProvider, ICustomFormatter
{
public ICustomFormatter Other;
public object GetFormat(Type service)
{
if (service == typeof(ICustomFormatter))
return this;
else
return null;
}
public string Format(string format, object arg, IFormatProvider provider)
{
if (arg == null || format == null)
if (Other == null)
return String.Format("{0}", arg);
else
return Other.Format(format, arg, provider);
if (arg is string || !(arg is IEnumerable))
if (Other != null)
return Other.Format(format, arg, provider);
else if (arg is IFormattable)
return ((IFormattable)arg).ToString(format, provider);
else
return arg.ToString();
string join, elemf;
var index = 0;
while (true)
{
index = format.IndexOf(';', index);
if (index < 0)
{
join = format;
elemf = null;
break;
}
if (index == 0)
{
join = "";
elemf = format.Substring(1);
break;
}
if (index == format.Length - 1)
{
join = format.Substring(0, format.Length - 1);
elemf = null;
break;
}
if (index > 0 && format[index - 1] == '!')
if (index > 1 && format[index - 2] == '!')
{
join = format.Substring(0, index - 1);
elemf = format.Substring(index + 1);
}
else
continue;
join = format.Substring(0, index);
elemf = format.Substring(index + 1);
break;
}
return String.Join(join, ((IEnumerable)arg).Cast<object>().Select((o, i) => elemf == null ? o.ToString() : String.Format(provider, elemf, o, i)));
}
}
答案 0 :(得分:0)
为了实现我的预期结果,我改为使用{{ {0:,;'{{0}}'} }}
。添加空格得到String.Format
以按照我想要的方式解释字符串。使用{{{<ArgNum>:<FormatStr>}}}
,它将前两个右括号解释为FormatStr
的一部分,将最后一个右括号解释为终止参数格式说明符。虽然我希望第一个右大括号终止参数格式说明符,但我希望最后两个右大括号将右大括号附加到输出。