String.Format计算预期args的数量

是否可以为String.Format()字符串中预期的args / params的数量?

例如: "Hello {0}. Bye {1}"应返回2的计数。

我需要在string.Format()抛出exception之前显示错误。

谢谢你的帮助。

您可以使用正则表达式,如{(。*?)},然后只计算匹配。 如果你需要处理像{0} {0}这样的情况(我想它应该返回1)那么这会让它变得有点困难,但是你总是可以把所有的匹配放在一个列表中,做一个Linq select distinct就可以了。 我在想类似下面的代码:

 var input = "{0} and {1} and {0} and {2:MM-dd-yyyy}"; var pattern = @"{(.*?)}"; var matches = Regex.Matches(input, pattern); var totalMatchCount = matches.Count; var uniqueMatchCount = matches.OfType().Select(m => m.Value).Distinct().Count(); Console.WriteLine("Total matches: {0}", totalMatchCount); Console.WriteLine("Unique matches: {0}", uniqueMatchCount); 

编辑:

我想解决评论中提出的一些问题。 下面发布的更新代码处理存在转义括号序列的情况(即{{5}}),其中未指定参数,并且还返回最高参数+ 1的值。代码假定输入字符串将形成良好,但在某些情况下,这种权衡是可以接受的。 例如,如果您知道输入字符串是在应用程序中定义的而不是由用户输入生成的,则可能不需要处理所有边缘情况。 也可以使用unit testing来测试要生成的所有错误消息。 我喜欢这个解决方案的是它很可能会处理抛出它的绝大多数字符串,并且它比这里指出的解决方案更简单(这表明string.AppendFormat的重新实现)。 我会解释这样的事实:这段代码可能无法通过使用try-catch处理所有边缘情况,只返回“无效的错误消息模板”或其他类似的东西。

下面代码的一个可能的改进是更新正则表达式而不返回前导“{”字符。 这将消除对Replace(“{”,string.Empty)的需要。 同样,这段代码在所有情况下可能并不理想,但我认为它充分解决了所提出的问题。

 const string input = "{0} and {1} and {0} and {4} {{5}} and {{{6:MM-dd-yyyy}}} and {{{{7:#,##0}}}} and {{{{{8}}}}}"; //const string input = "no parameters"; const string pattern = @"(?\{\{)*\{\d(.*?)"; var matches = Regex.Matches(input, pattern); var totalMatchCount = matches.Count; var uniqueMatchCount = matches.OfType().Select(m => m.Value).Distinct().Count(); var parameterMatchCount = (uniqueMatchCount == 0) ? 0 : matches.OfType().Select(m => m.Value).Distinct().Select(m => int.Parse(m.Replace("{", string.Empty))).Max() + 1; Console.WriteLine("Total matches: {0}", totalMatchCount); Console.WriteLine("Unique matches: {0}", uniqueMatchCount); Console.WriteLine("Parameter matches: {0}", parameterMatchCount); 

我认为这将处理Escape括号和0:0000的东西…将给出最大的括号值…所以在我的例子中将给出1。

  //error prone to malformed brackets... string s = "Hello {0:C} Bye {1} {0} {{34}}"; int param = -1; string[] vals = s.Replace("{{", "").Replace("}}", "").Split("{}".ToCharArray()); for (int x = 1; x < vals.Length-1; x += 2) { int thisparam; if (Int32.TryParse(vals[x].Split(',')[0].Split(':')[0], out thisparam) && param < thisparam) param = thisparam; } //param will be set to the greatest param now.