C#String.Format可选参数

我想使用带有optional parameters string.Format

 public static void Main(string[] args) { //Your code goes here // Console.WriteLine(string.Format("{0} {1}", "a", "b")); Console.WriteLine(string.Format("{0} {1}", "a")); } 

例如,参数{1}是可选的并具有默认值

你能帮我这么做吗?

谢谢

这取决于“可选参数”的含义。

如果要使用默认值自动替换null ,最简单的方法是在参数中使用null coalescing运算符:

 String.Format("{0} {1}", "a", someNullableVariableContainingB ?? "default value"); 

如果要为多个String.Format调用重用相同的格式化字符串,例如

 var myFormatString = "{0} {1}"; var string1 = String.Format(myFormatString, "a", "b"); var string2 = String.Format(myFormatString, "a"); 

那么你运气不好:如果提供的参数太少,String.Format 抛出exception,并且无法在格式字符串中指定“可选参数”。 您将不得不使用除String.Format之外的其他内容,例如,使用其预期的默认值替换缺少的参数的自定义方法。

该扩展方法不限于固定数量的参数。 也就是说,它可以使用"{0}"等字符串,还可以使用"{0} {1}""{0} {1} {2}"等字符串。 最小的缺点是,首先你提供可选参数,然后是非可选参数。 应该反过来但不幸的是params关键字的性质禁止这样做。 主要的缺点是它忽略了大括号中的数字(尽管解决方案可以重新设计以包含它)。

  public static string FormatOpt(this string s, string optional, params string[] param) { StringBuilder result = new StringBuilder(); int index = 0; bool opened = false; Stack stack = new Stack(param.Reverse()); foreach(var c in s) { if (c == '{') { opened = true; index = result.Length; } else if (opened && c == '}') { opened = false; var p = stack.Count > 0 ? stack.Pop() : optional; var lenToRem = result.Length - index; result.Remove(index, lenToRem); result.Append(p); continue; } else if (opened && !Char.IsDigit(c)) { opened = false; } result.Append(c); } return result.ToString(); } 

并且有预期的结果:

 string res1 = "result: {0}, {1}, {2}, {3}".FormatOpt("optional", "first param", "second param"); // result: first param, second param, optional, optional string res2 = "result: {0}, {1}, {2}, {3}".FormatOpt("optional", "first param"); // result: first param, optional, optional, optional string res3 = "result: {0}, {1}, {2}, {3}".FormatOpt("optional"); // result: optional, optional, optional, optional 
  private static Regex curlyBracketRegex = new Regex("\\{(.+?)\\}"); private static string OptionalFormat(string formatString, params object[] args) { var numberOfArguments = curlyBracketRegex.Matches(formatString).Count; var missingArgumentCount = numberOfArguments - args.Length; if (missingArgumentCount <= 0) //more argument or just enough return string.Format(formatString, args); args = args.Concat(Enumerable.Range(0, missingArgumentCount).Select(_ => string.Empty)).ToArray(); return string.Format(formatString, args); } 

上面的方法适用于简单的格式字符串。 正则表达式检测大括号。 如果匹配计数高于传递的args的数量,则将创建一个新数组,将原始数组与空字符串组合在一起。

示例:OptionalFormat(“{0}#{1}”,“apple”)// apple#

您可以创建一个扩展方法:

 public static string MyFormat(this string s, int i, params string[] args){ var t = new List(args); for(var c = t.Count; c < i; ++c) t.Add(String.Empty); // or other default return String.Format(s, t.ToArray()); } 

并致电:

 "{0}:{1} - {2},{3},{4}".MyFormat(5, "ping", "fnord"); 

但是它会强制您按顺序指定参数,因此如果要设置{4},则不能跳过{3}。 但是你可以添加:

 for(var x = 0; x < args.Count; ++x){ if(args[x] == null) args[x] = String.Empty; 

并致电:

 "{0}:{1} - {2},{3},{4}".MyFormat(5, "ping", null, "pong"); 

设置{0}和{2},但默认为{1},{3}和{4}为String.Empty;

你可以自动确定i,但这样就容易多了。