String.Format计算预期args的数量

时间:2011-02-14 05:29:14

标签: c# .net string

是否可以计算String.Format()字符串中预期的参数/参数的数量?

例如:"Hello {0}. Bye {1}"应返回2.

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

感谢您的帮助。

3 个答案:

答案 0 :(得分:13)

您可以使用正则表达式,如{(。*?)},然后只计算匹配。如果你需要处理像{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<Match>().Select(m => m.Value).Distinct().Count();
Console.WriteLine("Total matches: {0}", totalMatchCount);
Console.WriteLine("Unique matches: {0}", uniqueMatchCount);

修改

我想解决评论中提出的一些问题。下面发布的更新代码处理存在转义括号序列的情况(即{{5}}),其中未指定参数,并且还返回最高参数+ 1的值。代码假定输入字符串将形成良好,但在某些情况下可以接受这种权衡。例如,如果您知道输入字符串是在应用程序中定义的而不是由用户输入生成的,则可能不需要处理所有边缘情况。也可以使用单元测试来测试要生成的所有错误消息。我喜欢这个解决方案的是它很可能会处理抛出它的绝大多数字符串,并且它比标识here的更简单的解决方案(这表明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<Match>().Select(m => m.Value).Distinct().Count();
var parameterMatchCount = (uniqueMatchCount == 0) ? 0 : matches.OfType<Match>().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);

答案 1 :(得分:3)

我认为这会处理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.

答案 2 :(得分:0)

此简单方法可以轻松解决此问题:

public static int CountArguments(string str)
    {
        int quantity= 0;
        while(str.Contains("{" + quantity+ "}"))
        {
            quantity++;
        }
        return quantity;
    }