簡體   English   中英

C# String.Format 可選參數

[英]C# String.Format optional parameters

我想使用帶有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 合並運算符:

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拋出異常,並且無法在格式字符串中指定“可選參數”。 您將不得不使用 String.Format 以外的其他東西,例如,一個自定義方法,用其預期的默認值替換缺少的參數。

您可以創建一個擴展方法:

public static string MyFormat(this string s, int i, params string[] args){
    var t = new List<string>(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,但像這樣更容易。

這種擴展方法不限於固定數量的參數。 也就是說,它可以處理像"{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<string> stack = new Stack<string>(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#

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM