【问题标题】:Why use String.Format? [duplicate]为什么使用 String.Format? [复制]
【发布时间】:2011-06-07 23:33:39
【问题描述】:

为什么有人会在 C# 和 VB .NET 中使用 String.Format 而不是串联运算符(VB 中的 & 和 C# 中的 +)?

主要区别是什么?为什么大家对使用String.Format 如此感兴趣?我很好奇。

【问题讨论】:

标签: c# string vb.net string.format


【解决方案1】:

我可以看到很多原因:

可读性

string s = string.Format("Hey, {0} it is the {1}st day of {2}.  I feel {3}!", _name, _day, _month, _feeling);

对比:

string s = "Hey," + _name + " it is the " + _day + "st day of " + _month + ".  I feel " + feeling + "!";

格式说明符 (这包括您可以编写自定义格式化程序的事实)

string s = string.Format("Invoice number: {0:0000}", _invoiceNum);

对比:

string s = "Invoice Number = " + ("0000" + _invoiceNum).Substr(..... /*can't even be bothered to type it*/)

字符串模板持久性

如果我想在数据库中存储字符串模板怎么办?带字符串格式:

_id         _translation
  1         Welcome {0} to {1}.  Today is {2}.
  2         You have {0} products in your basket.
  3         Thank-you for your order.  Your {0} will arrive in {1} working days.

对比:

_id         _translation
  1         Welcome
  2         to
  3         .  Today is
  4         . 
  5         You have
  6         products in your basket.
  7         Someone
  8         just shoot
  9         the developer.

【讨论】:

  • Someone just shoot the developer. +1 ;-)
  • 对于您的“substr”示例,您实际上应该使用 _invoiceNum.ToString("00000")。 ToString 支持与 string.Format() 相同的复合格式设置当您只有一个要格式化的值时,ToString() 通常比 Format() 更简单/更清晰。
  • 我不了解你,但我阅读了没有格式化的更好。特别是当我想知道什么去哪里的时候,我必须在文本和参数之间来回走动,这甚至还没有计算错误计数和弄错的可能性(这可能不是参数较少的问题,但是去超过 10 并且它不再有趣)。正如 Ashley 指出的那样,如果您使用 ToString 方法中内置的格式,则第二点为空。我同意第三个,但我认为我不会在那个特殊情况之外使用它。
  • +1 - 也使用String.Format 更快并且使用更少的开销。使用 concat +/& 每次都必须重建字符串,这在大字符串对象中可能非常糟糕。 string 的真正定义是它应该定义一次并重用多次。(许多书教我们使用 concat 作为示例,但从不告诉我们性能!)构建字符串应该使用 StringBuilder 更快比String.Format !非常好的答案 - 开发人员需要学习编写可读代码并牢记性能!
  • @ppumkin 这不是真的。当您在单个表达式中指定了特定数量的 + 运算符时,编译器会将其转换为对 string.Concat 的单个调用,并且不会创建任何中间字符串。使用 StringBuilder 实际上会伤害 性能,而不是帮助它,因为 Concat 可以从一开始就创建一个大小正好合适的内部缓冲区。当您有某种循环或其他控制块时使用 SB,这样编译器在编译时不知道要连接的字符串的数量。
【解决方案2】:

除了更易于阅读和添加更多运算符之外,如果您的应用程序是国际化的,这也是有益的。很多时候,变量是数字或关键词,它们对于不同的语言会有不同的顺序。通过使用 String.Format,您的代码可以保持不变,而不同的字符串将进入资源文件。所以,代码最终会是

String.Format(resource.GetString("MyResourceString"), str1, str2, str3);

虽然你的资源字符串最终是

英文:"blah blah {0} blah blah {1} blah {2}"

俄语:"{0} blet blet blet {2} blet {1}"

俄语对于事物的处理方式可能有不同的规则,因此顺序不同或句子结构不同。

【讨论】:

  • +1 在看到这个之前,我从未考虑过 String.Format 的本地化应用。
【解决方案3】:

首先,我发现

string s = String.Format(
    "Your order {0} will be delivered on {1:yyyy-MM-dd}. Your total cost is {2:C}.",
    orderNumber,
    orderDeliveryDate,
    orderCost
);

比阅读、编写和维护要容易得多

string s = "Your order " +
           orderNumber.ToString() +
           " will be delivered on " +
           orderDeliveryDate.ToString("yyyy-MM-dd") +
           "." +
           "Your total cost is " +
           orderCost.ToString("C") + 
           ".";

看看下面的可维护性有多少

string s = String.Format(
    "Year = {0:yyyy}, Month = {0:MM}, Day = {0:dd}",
    date
);

在另一种情况下,您必须重复 date 三次。

其次,String.Format 提供的格式说明符为您提供了极大的字符串输出灵活性,这种方式比仅使用普通的旧连接更易于阅读、编写和维护。此外,使用String.Format 更容易解决文化问题。

第三,当性能很重要时,String.Format 将优于串联。在幕后它使用StringBuilder 并避免使用Schlemiel the Painter problem

【讨论】:

  • 请注意:在一行中重复 +s 不存在 Schlemiel the Painter 问题。它们被编译为单个 string.Concat 调用。
  • 实际上string.Concat 优于String.Format(至少对于单个短字符串)。然而,其中涉及许多因素(这可以使一个比另一个更有效)。在执行时间很重要的情况下(无数次重复相同的操作),使用string.Concat 节省的速度虽然可以忽略不计。
  • 您不必显式调用 ToString()。 "Your order " + orderNumber.ToString()"Your order " + orderNumber 相同
  • +s 实际上存在 Schlemiel the Painter 问题,只是有点延迟。 String.Concat 最多只需要四个参数,因此通过+s 连接五个或更多字符串的方式是将它们连接成最多四个一组,然后连接 那些 字符串,等等开。
【解决方案4】:

几个原因:

  1. String.Format() 非常强大。您可以在格式字符串中使用简单的格式指示符(如固定宽度、货币、字符长度等)。您甚至可以创建自己的格式提供程序,用于扩展枚举、将特定输入映射到更复杂的输出或本地化。
  2. 您可以通过将格式字符串放入配置文件中来做一些强大的事情。
  3. String.Format() 通常更快,因为它在后台使用StringBuilder 和高效的状态机,而.Net 中的字符串连接相对较慢。对于小字符串,差异可以忽略不计,但随着字符串大小和替换值数量的增加,差异会很明显。
  4. String.Format() 实际上对许多程序员来说更为熟悉,尤其是那些来自使用旧 C printf() 函数变体的背景的程序员。

最后,别忘了StringBuilder.AppendFormat()String.Format()实际上在幕后使用了这种方法*,直接去StringBuilder可以给你一种混合方法:显式使用.Append()(类似于连接)对于一个大字符串的某些部分,并使用@ 987654331@在其他人。


* [edit] 原来的答案现在已经有 8 年历史了,从那以后我看到了一个迹象,当字符串插值添加到 .Net 时,这可能已经改变了。但是,我还没有返回参考源来验证更改。

【讨论】:

  • string.Format 通常不会比几个字符串连接快,因为格式字符串也需要解析和复制。
  • 感谢您的更新。事实上,string.Format 与串联 + ToString() 相比还有另一个警告:值类型被装箱,如下所述:jeffbarnes.net/blog/post/2006/08/08/…。尽管如此,string.Format 是一个非常强大和出色的工具,性能通常不是最重要的标准。
  • 参考#3:字符串生成器并不比连接快。实际在不同行(或循环中)进行连接的“测试”支持它的神话。当所有连接都在一行上完成时,编译器会将其转换为 string.append(paramaarray) 调用,这是所有选项中效率最高的。在 string.append 调用期间,目标字符串的确切大小是提前知道的,可以立即分配,每个字符只复制一次。
【解决方案5】:

String.Format 除了连接运算符之外还添加了许多选项,包括指定添加到字符串中的每个项目的特定格式的能力。

有关可能的详细信息,我建议阅读 MSDN 上标题为 Composite Formatting 的部分。它解释了String.Format(以及xxx.WriteLine 和其他支持复合格式的方法)相对于普通连接运算符的优势。

【讨论】:

  • 字符串格式很好但比连接慢。说得够多了。
【解决方案6】:

this question 中有一些关于性能方面的有趣内容

但我个人仍会推荐string.Format,除非出于可读性原因,性能至关重要。

string.Format("{0}: {1}", key, value);

更具可读性
key + ": " + value

例如。还提供了很好的关注点分离。意味着你可以拥有

string.Format(GetConfigValue("KeyValueFormat"), key, value);

然后将您的键值格式从 "{0}: {1}" 更改为 "{0} - {1}" 成为配置更改而不是代码更改。

string.Format 还内置了一堆格式设置,整数,日期格式等。

【讨论】:

【解决方案7】:

不宜写成'string +"Value"+ string' 这样的字符串的一个原因是本地化。在发生本地化的情况下,我们希望本地化字符串的格式正确,这可能与编码的语言非常不同。

例如我们需要用不同的语言显示以下错误:

MessageBox.Show(String.Format(ErrorManager.GetError("PIDV001").Description, proposalvalue.ProposalSource)

在哪里

'ErrorCollector.GetError("ERR001").ErrorDescription' 返回一个类似"Your ID {0} is not valid" 的字符串。此消息必须以多种语言本地化。在这种情况下,我们不能在 C# 中使用 +。我们需要遵循 string.format。

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 2017-11-24
    • 2015-11-13
    相关资源
    最近更新 更多