string.Format等效,不会因额外的标记而抛出异常

时间:2017-11-15 08:12:47

标签: c# .net string .net-4.0 string-formatting

我希望我的应用程序的最终用户编辑string.Format中使用的格式字符串。我想这样做是为了让用户能够编辑模板。当用户输入太多标记时会出现问题。

这很好用:

var result = string.Format("test {0}, {1}, {2}", 1, 2, 3);

这也有效:

var result = string.Format("test {0}, {1}", 1, 2, 3);

但这引发了异常:

var result = string.Format("test {0}, {1}, {2}", 1, 2);
  

System.FormatException:'索引(从零开始)必须大于或   等于零且小于参数列表的大小。'

我知道我必须添加与标记一样多的参数,但最终用户不知道,或者他可以犯错误 - 添加额外的标记。

我的问题是:
我可以使用类似的方法来格式化字符串string.Format,但无一例外。

我知道我可以使用try\catch阻止并返回格式字符串,但我不想这样做。

我构建了一个非常简单的方法来替换字符串中的标记:

public static string SafeFormat(string format, params object[] args)
{
    var result = format;
    for (int i = 0; i < args.Length; i++)
    {
        result = result.Replace($"{{{i}}}", args[i].ToString());
    }
    return result;
}

但这不支持使用代替标记的数据格式化。

内部string.Format正在使用比我的简单替换更复杂的AppendFormatHelperhttp://referencesource.microsoft.com/#mscorlib/system/text/stringbuilder.cs,2c3b4c2e7c43f5a4)。

理想情况下,string.Format("test {0}, {1}, {2}", 1, 2)应返回test 1, 2, {2}

1 个答案:

答案 0 :(得分:1)

一种解决方案是检查预期的值数,并将其他值附加到参数列表(null或占位符)。示例字符串扩展名:

public static class StringExtensions
{
    public static string SafeFormat(this string value, params object[] args)
    {
        var pattern = @"{(.*?)}";
        var matches = Regex.Matches(value, pattern);
        var matchCount = matches.Count;
        if (matchCount > args.Length)
        {
            var argsExtended = args.ToList();
            for (int i = args.Length; i < matchCount; i++)
            {
                argsExtended.Add($"{{{i}}}"); //Can add null value to erase them
            }
            return string.Format(value, argsExtended.ToArray());
        }
        return string.Format(value, args);
    }
}

如果需要,可以轻松将其更改为方法