如何在 .Net 中有条件地格式化字符串?

33

我想对字符串进行一些条件格式化。我知道你可以像下面这样对整数和浮点数进行一些条件格式化:

Int32 i = 0;
i.ToString("$#,##0.00;($#,##0.00);Zero");

如果变量为正数、负数或零,则上述代码将导致三种格式之一。

我想知道是否有办法在字符串参数上使用节段。以一个具体但虚构的示例为例,我会尝试替换以下代码中的“if”检查:

string MyFormatString(List<String> items, List<String> values)
{
    string itemList = String.Join(", " items.ToArray());
    string valueList = String.Join(", " values.ToArray());

    string formatString;

    if (items.Count > 0)
    //this could easily be: 
    //if (!String.IsNullOrEmpty(itemList))
    {
        formatString = "Items: {0}; Values: {1}";
    }
    else
    {
        formatString = "Values: {1}";
    }

    return String.Format(formatString, itemList, valueList);
}
7个回答

37

你可以使用条件运算符来简化它:

string formatString = items.Count > 0 ? "Items: {0}; Values: {1}" : "Values: {1}";
return string.Format(formatString, itemList, valueList);

或者将它包含在同一语句中:

return string.Format(items.Count > 0 ? "Items: {0}; Values: {1}" : "Values: {1}",
                     itemList, valueList);

这符合您的要求吗?我认为你不能拥有一个单一的格式字符串,有时包含一些部分,有时则没有。


4
不确定为什么这个回答被投票否决,因为它确实有效...有没有投票者愿意启迪我?了解人们不喜欢答案的原因总是件好事 - 这将使我们更容易在未来提供更好的答案。 - Jon Skeet
7
如果情况超过两种,我会仔细查看这些情况是什么。我可能会使用switch语句。但我肯定认为这比使用if/else更简单。如果你对条件运算符不太熟悉,那没关系——但显然不只我认为它简化了代码,因为大多数答案都建议使用它。你认为它“绝对奇怪”是什么让你这样想的呢?(顺便说一下,“ternary if”不是它的名称——它是条件运算符。) - Jon Skeet
2
@loki2302:所以你从来没有一个语句有多个表达式,也从不使用条件运算符?听起来对我来说像是一种乏味的代码风格。将事情分解成更小的部分是有其适用的场景(我刚回答了另一个类似的问题,在那里一个表达式中做太多的事情使得诊断问题变得困难),但也需要保持平衡。你一定非常讨厌LINQ,因为你被鼓励使用组合来链接一堆操作... - Jon Skeet
2
@loki2302:所以将属性链接在一起是个大忌,但链式调用方法就可以?这对我来说很奇怪。我猜我们必须同意不同意见 - 你的立场对我来说似乎太极端了。需要保持平衡,我从来没有建议在单个语句中完成太多操作 - 但在这里,我们有三个非常简单的表达式和一个简单的方法调用,因此通过条件运算符将它们组合起来似乎完全没问题。 - Jon Skeet
这种技术非常适用于有条件地格式化Web Forms中的ItemTemplate文本。以前从未想过在String.Format函数内放置?运算符。 - Dan Randolph
显示剩余8条评论

6
不在String.Format()中,但是你可以使用C#的内联运算符,例如:
return items.Count > 0 
       ? String.Format("Items: {0}; Values: {1}", itemList, valueList)
       : String.Format("Values: {0}", valueList);           

这将有助于整理代码。

5

虽然没有直接回答OP的问题,但这也与问题标题有关。

我经常需要使用一些自定义单位来格式化字符串,但在没有数据的情况下,我不想输出任何内容。我将其与各种可空类型一起使用:

/// <summary>
/// Like String.Format, but if any parameter is null, the nullOutput string is returned.
/// </summary>
public static string StringFormatNull(string format, string nullOutput, params object[] args)
{
    return args.Any(o => o == null) ? nullOutput : String.Format(format, args);
}

例如,如果我正在格式化像“20°C”这样的温度,但遇到空值,它将打印替代字符串而不是“°C”。
double? temp1 = 20.0;
double? temp2 = null;

string out1 = StringFormatNull("{0}°C", "N/A", temp1); // "20°C"
string out2 = StringFormatNull("{0}°C", "N/A", temp2); // "N/A"

2
string.Format(  (items.Count > 0 ? "Items: {0}; " : "") + "Values {1}"
              , itemList
              , valueList); 

你能告诉我具体规定从0开始且没有缺失数字的文档在哪里吗? - Adam Tegen
我搞错了——我把它和所有占位符数字都小于参数列表长度的要求混淆了。空参数是可以的,因为它们会被转换为空字符串。 - Mark Cidade

1

不要这样做。我不知道你代码中的项目和值是什么,但我相信,这对可以被视为某种实体。将此实体定义为一个类,并重写其ToString()方法以返回任何你想要的内容。根据某些上下文决定如何格式化此字符串,使用if完全没有问题。


0

希望这个可以做到:

return String.Format(items.ToString(itemList + " ;;") + "Values: {0}", valueList);

很遗憾,似乎.ToString()方法不支持空白的负数和零选项,或者没有在任何地方使用#或0。我会把它留在这里,以防它能指引其他人找到更好的答案。

0

这可能不是你想要的,但是怎么样...

formatString = (items.Count > 0) ? "Items: {0}; Values: {1}" : "Values: {1}";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接