String.Format计算预期参数的数量 [英] String.Format count the number of expected args

查看:190
本文介绍了String.Format计算预期参数的数量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



例如:你好{0}。再见{1} 应该返回2。 / p>

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



感谢您的帮助。

解决方案

您可以使用正则表达式,例如{(。 *?)},然后只计算匹配项。如果您需要处理{0} {0}之类的情况(我猜应该返回1),那么这会有点困难,但是您始终可以将所有匹配项都放在列表中,并在其上进行Linq select区别选择。我在想类似下面的代码:

  var input = {0} and {1} and {0} and {2:MM-dd-yyyy}; 
var pattern = @ {(。*?)} ;;
var matchs = Regex.Matches(input,pattern);
var totalMatchCount = match.Count;
var uniqueMatchCount = match.OfType< Match>()。Select(m => m.Value).Distinct()。Count();
Console.WriteLine(总匹配项:{0},totalMatchCount);
Console.WriteLine(唯一匹配项:{0},uniqueMatchCount);

编辑:



我想解决评论中提出的一些问题。下面发布的更新代码处理了转义括号序列(即{{5}}),未指定参数的情况,并返回最高参数+ 1的值。该代码假定输入字符串将格式良好,但在某些情况下可以权衡取舍。例如,如果您知道输入字符串是在应用程序中定义的,而不是由用户输入生成的,则可能不需要处理所有边缘情况。也可能使用单元测试来测试所有要生成的错误消息。我喜欢这种解决方案的地方在于,它很可能会处理抛出的绝大多数字符串,并且比确定的(这表示重新实现字符串.AppendFormat)。我会考虑这样一个事实,即该代码可能无法通过使用try-catch并仅返回无效错误消息模板或类似结果来处理所有极端情况。



以下代码的一个可能的改进是更新正则表达式,使其不返回前导 {字符。这将消除对Replace( {,string.Empty)的需要。同样,此代码可能并非在所有情况下都是理想的,但我认为它足以解决所问的问题。

  const字符串输入= {0}和{1}以及{0}和{4} {{5}}和{{{6:MM-dd-yyyy}}}和{{{{7:#,## 0}} }}和{{{{{{8}}}}}; 
//常量字符串输入=无参数;
const string pattern = @(?<!\ {)(?> \ {\ {)* \ {\d(。*?) ;;
var matchs = Regex.Matches(input,pattern);
var totalMatchCount = match.Count;
var uniqueMatchCount = match.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(总匹配项:{0},totalMatchCount);
Console.WriteLine(唯一匹配项:{0},uniqueMatchCount);
Console.WriteLine(参数匹配:{0},parameterMatchCount);


Is it possible to count the number of expected args/params in a string for String.Format()?

For example: "Hello {0}. Bye {1}" should return a count of 2.

I need to display an error before the string.Format() throws an exception.

Thanks for your help.

解决方案

You could use a regex, something like {(.*?)} and then just count the matches. If you need to handle cases like {0} {0} (which I guess should return 1) then that makes it a little more difficult, but you could always put all of the matches in a list an do a Linq select distinct on it. I'm thinking something like the code below:

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);

EDIT:

I wanted to address some of the concerns raised in the comments. The updated code posted below handles the cases where there are escaped bracket sequences (i.e., {{5}}), where no parameters are specified, and also returns the value of the highest parameter + 1. The code assumes that the input strings will be well formed, but that trade off may be acceptable in some cases. For example, if you know that the input strings are defined in an application and not generated by user input, then handling all of the edge cases may not be necessary. It might also be possible to test all of the error messages to be generated using a unit test. The thing I like about this solution is that it will most likely handle the vast majority of the strings that are thrown at it, and it is a simpler solution than the one identified here (which suggests a reimplementation of string.AppendFormat). I would account for the fact that this code might not handle all edge cases by using a try-catch and just returning "Invalid error message template" or something to that effect.

One possible improvement for the code below would be to update the regex to not return the leading "{" characters. That would eliminate the need for the Replace("{", string.Empty). Again, this code might not be ideal in all cases, but I feel it adequately addresses the question as asked.

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);

这篇关于String.Format计算预期参数的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆