C# 什么时候使用 String.Format 与字符串连接更好?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/296978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 22:08:02  来源:igfitidea点击:

When is it better to use String.Format vs string concatenation?

c#.netstring

提问by Gavin Miller

I've got a small piece of code that is parsing an index value to determine a cell input into Excel. It's got me thinking...

我有一小段代码可以解析索引值以确定 Excel 中的单元格输入。这让我想...

What's the difference between

有什么区别

xlsSheet.Write("C" + rowIndex.ToString(), null, title);

and

xlsSheet.Write(string.Format("C{0}", rowIndex), null, title);

Is one "better" than the other? And why?

这个比那个好吗?为什么?

采纳答案by Jon Skeet

Before C# 6

在 C# 6 之前

To be honest, I think the first version is simpler - although I'd simplify it to:

老实说,我认为第一个版本更简单 - 尽管我会将其简化为:

xlsSheet.Write("C" + rowIndex, null, title);

I suspect other answers maytalk about the performance hit, but to be honest it'll be minimal if present at all- and this concatenation version doesn't need to parse the format string.

我怀疑其他答案可能会谈论性能影响,但老实说,如果存在的话,它会很小- 而且这个连接版本不需要解析格式字符串。

Format strings are great for purposes of localisation etc, but in a case like this concatenation is simpler and works just as well.

格式字符串非常适合用于本地化等目的,但在这种情况下,这种连接更简单,也能正常工作。

With C# 6

使用 C# 6

String interpolation makes a lot of things simpler to read in C# 6. In this case, your second code becomes:

字符串插值使 C# 6 中的许多内容更易于阅读。在这种情况下,您的第二个代码变为:

xlsSheet.Write($"C{rowIndex}", null, title);

which is probably the best option, IMO.

这可能是最好的选择,IMO。

回答by Aaron Palmer

If your string was more complex with many variables being concatenated, then I would choose the string.Format(). But for the size of string and number of variables being concatenated in your case, I'd go with your first version, it's more spartan.

如果您的字符串更复杂,并且连接了许多变量,那么我会选择 string.Format()。但是对于在您的情况下连接的字符串的大小和变量的数量,我会使用您的第一个版本,它更加spartan

回答by Joel Coehoorn

That example is probably too trivial to notice a difference. In fact, I think in most cases the compiler can optimize away any difference at all.

这个例子可能太微不足道了,无法注意到差异。事实上,我认为在大多数情况下,编译器完全可以优化掉任何差异。

However, if I had to guess I'd give string.Format()an edge for more complicated scenarios. But that's more of a gut feeling that's it's likely to do a better job utilizing a buffer instead of producing multiple immutable strings, and not based on any real data.

但是,如果我不得不猜测,我会string.Format()为更复杂的场景提供优势。但这更像是一种直觉,即使用缓冲区而不是生成多个不可变字符串可能会做得更好,而不是基于任何真实数据。

回答by CMS

I like String.Format because can make your formatted text much easier to follow and read than inline concatenation, also its much more flexible allowing you to format your parameters, however for short uses like yours I see no problem about concatenating.

我喜欢 String.Format 因为它可以让你的格式化文本比内联连接更容易理解和阅读,而且它更灵活地允许你格式化你的参数,但是对于像你这样的短期使用,我认为连接没有问题。

For concatenations inside loops or in big strings you should always try to use the StringBuilder class.

对于循环内或大字符串中的连接,您应该始终尝试使用 StringBuilder 类。

回答by CMS

String concatenation takes more memory compared to String.Format. So best way to concatenate strings is using String.Format or System.Text.StringBuilder Object.

与 String.Format 相比,字符串连接需要更多内存。因此连接字符串的最佳方法是使用 String.Format 或 System.Text.StringBuilder 对象。

Let's take first case: "C" + rowIndex.ToString() Let's assume rowIndex is a value type so ToString() method has to Box to convert the value to String and then CLR creates memory for the new string with both values included.

让我们采用第一种情况:"C" + rowIndex.ToString() 假设 rowIndex 是一个值类型,所以 ToString() 方法必须将值转换为 String,然后 CLR 为包含这两个值的新字符串创建内存。

Where as string.Format expects object parameter and takes in rowIndex as an object and converts it to string internally offcourse there will be Boxing but it's intrinsic and also it's won't take up as much memory as in first case.

string.Format 需要对象参数并将 rowIndex 作为对象并将其在内部转换为字符串,当然会有 Boxing 但它是内在的,而且它不会像第一种情况那样占用那么多内存。

For short strings it won't matter that much I guess...

对于短字符串,我猜没有那么重要......

回答by Martin Hollingsworth

I think the first option is more readable and that should be your primary concern.

我认为第一个选项更具可读性,这应该是您的主要关注点。

xlsSheet.Write("C" + rowIndex.ToString(), null, title);

string.Format uses a StringBuilder under the hood (check with reflector) so it won't have any performance benefit unless you are doing a significant amount of concatenation. It will be slower for your scenario but the reality is this micro performance optimisation decision is inappropriate most of the time and you should really be focusing on the readability of your code unless you are in a loop.

string.Format 在引擎盖下使用 StringBuilder (检查反射器)所以它不会有任何性能优势,除非您进行大量连接。对于您的场景,它会更慢,但现实是这种微性能优化决定在大多数情况下是不合适的,除非您处于循环中,否则您应该真正关注代码的可读性。

Either way, write for readability first and then use a performance profilerto identify your hotspots if you really think you have performance concerns.

无论哪种方式,如果您真的认为您有性能问题,请首先编写可读性,然后使用性能分析器来确定您的热点。

回答by P Daddy

For a simple case where it's a simple single concatenation, I feel that it's not worth the complexity of string.Format(and I haven't tested, but I suspect that for a simple case like this, string.Formatmightbe slightly slower, what with the format string parsing and all). Like Jon Skeet, I prefer to not explicitly call .ToString(), since that will be done implicitly by the string.Concat(string, object)overload, and I think the code is cleaner-looking and easier to read without it.

对于一个简单的单个串联的简单情况,我觉得不值得复杂性string.Format(我还没有测试过,但我怀疑对于这样的简单情况,string.Format可能会稍微慢一点,格式字符串解析是什么和所有)。像 Jon Skeet 一样,我更喜欢不显式调用.ToString(),因为这将由string.Concat(string, object)重载隐式完成,而且我认为没有它,代码看起来更清晰,更容易阅读。

But for more than a few concatenations (how many is subjective), I definitely prefer string.Format. At a certain point I think that both readability and performance suffer unnecessarily with concatenation.

但是对于多个串联(多少是主观的),我绝对更喜欢string.Format. 在某种程度上,我认为可读性和性能都会因串联而受到不必要的影响。

If there are many parameters to the format string (again, "many" is subjective), I usually prefer to include commented indices on the replacement arguments, lest I lose track of which value goes to which parameter. A contrived example:

如果格式字符串有很多参数(同样,“许多”是主观的),我通常更喜欢在替换参数中包含注释索引,以免我忘记哪个值属于哪个参数。一个人为的例子:

Console.WriteLine(
    "Dear {0} {1},\n\n" +

    "Our records indicate that your {2}, \"{3}\", is due for {4} {5} shots.\n" +
    "Please call our office at 1-900-382-5633 to make an appointment.\n\n" +

    "Thank you,\n" +
    "Eastern Veterinary",

    /*0*/client.Title,
    /*1*/client.LastName,
    /*2*/client.Pet.Animal,
    /*3*/client.Pet.Name,
    /*4*/client.Pet.Gender == Gender.Male ? "his" : "her",
    /*5*/client.Pet.Schedule[0]
);


Update

更新

It occurs to me that the example I've given is a bit confusing, because it appears that I've used bothconcatenation and string.Formathere. And yes, logically and lexically, that's what I've done. But the concatenations will all be optimized away by the compiler1, since they're all string literals. So at run-time, there will be a single string. So I guess I should say that I prefer to avoid many concatenations at run time.

我发现我给出的例子有点令人困惑,因为我似乎同时使用连接和string.Format这里。是的,在逻辑和词汇上,这就是我所做的。但是连接都会被编译器1优化掉,因为它们都是字符串文字。所以在运行时,会有一个字符串。所以我想我应该说我更喜欢在运行时避免许多串联。

Of course, most of this topic is out of date now, unless you're still stuck using C# 5 or older. Now we have interpolated strings, which for readability, are far superior to string.Format, in almost all cases. These days, unless I'm just concatenating a value directly to the beginning or end of a string literal, I almost always use string interpolation. Today, I'd write my earlier example like this:

当然,这个主题的大部分内容现在已经过时,除非您仍然坚持使用 C# 5 或更早版本。现在我们已经插入了字符串,它的可读性string.Format在几乎所有情况下都远远优于。现在,除非我只是将一个值直接连接到字符串文字的开头或结尾,否则我几乎总是使用字符串插值。今天,我会像这样写我之前的例子:

Console.WriteLine(
    $"Dear {client.Title} {client.LastName},\n\n" +

    $"Our records indicate that your {client.Pet.Animal}, \"{client.Pet.Name}\", " +
    $"is due for {(client.Pet.Gender == Gender.Male ? "his" : "her")} " +
    $"{client.Pet.Schedule[0]} shots.\n" +
    "Please call our office at 1-900-382-5633 to make an appointment.\n\n" +

    "Thank you,\n" +
    "Eastern Veterinary"
);

You do lose compile-time concatenation this way.Each interpolated string gets turned into a call to string.Formatby the compiler, and their results are concatenated at run time. That means this is a sacrifice of run-time performance for readability. Most of the time, it's a worthwhile sacrifice, because the run-time penalty is negligible. In performance critical code, however, you may need to profile different solutions.

您确实会以这种方式丢失编译时连接。每个插入的字符串都被string.Format编译器转换为对的调用,并且它们的结果在运行时被连接起来。这意味着这是为了可读性而牺牲了运行时性能。大多数情况下,这是值得的牺牲,因为运行时损失可以忽略不计。但是,在性能关键代码中,您可能需要分析不同的解决方案。



1You can see this in the C# specification:

1您可以在C# 规范中看到这一点:

... the following constructs are permitted in constant expressions:

...

  • The predefined + ... binary operator...

...常量表达式中允许使用以下结构:

...

  • 预定义的 + ... 二元运算符...

You can also verify it with a little code:

你也可以用一点代码来验证:

const string s =
    "This compiles successfully, " +
    "and you can see that it will " +
    "all be one string (named `s`) " +
    "at run time";

回答by pipTheGeek

I have taken a look at String.Format (using Reflector) and it actually creates a StringBuilder then calls AppendFormat on it. So it is quicker than concat for multiple stirngs. Quickest (I believe) would be creating a StringBuilder and doing the calls to Append manually. Of course the number of "many" is up for guessing. I would use + (actually & becuase I am a VB programmer mostly) for something as simple as your example. As it gets more complex I use String.Format. If there are LOTS of variables then I would go for a StringBuilder and Append, for example, we have code that builds code, there I use one line of actual code to output one line of generated code.

我查看了 String.Format(使用 Reflector),它实际上创建了一个 StringBuilder,然后在其上调用 AppendFormat。因此,对于多个搅拌,它比 concat 更快。最快(我相信)将创建一个 StringBuilder 并手动调用 Append 。当然,“许多”的数量有待猜测。我会使用 + (实际上 & 因为我主要是一个 VB 程序员)来做一些像你的例子一样简单的事情。随着它变得更复杂,我使用 String.Format。如果有很多变量,那么我会选择 StringBuilder 和 Append,例如,我们有构建代码的代码,在那里我使用一行实际代码来输出一行生成的代码。

There seems to be some speculation about how many strings get created for each of these operations, so lets take a few simple examples.

似乎有一些关于为这些操作中的每一个创建多少字符串的猜测,所以让我们举几个简单的例子。

"C" + rowIndex.ToString();

"C" is already a string.
rowIndex.ToString() creates another string. (@manohard - no boxing of rowIndex will occur)
Then we get the final string.
If we take the example of

“C”已经是一个字符串。
rowIndex.ToString() 创建另一个字符串。(@manohard - 不会发生 rowIndex 的装箱)
然后我们得到最终的字符串。
如果我们以

String.Format("C(0)",rowIndex);

then we have "C{0}" as a string
rowIndex gets boxed to be passed to the function
A new stringbuilder is created
AppendFormat is called on the string builder - I don't know the details of how AppendFormat functions but lets assume it is ultra efficient, it is still going to have to convert the boxed rowIndex into a string.
Then convert the stringbuilder into a new string.
I know that StringBuilders attempt to prevent pointless memory copies from taking place but the String.Format still ends up with extra overhead compared to the plain concatenation.

然后我们有“C{0}”作为字符串
rowIndex被装箱传递给函数
一个新的
stringbuilder被创建在字符串构建器上调用AppendFormat - 我不知道AppendFormat如何运作的细节,但让我们假设它是超高效,它仍然必须将装箱的 rowIndex 转换为字符串。
然后将 stringbuilder 转换为新字符串。
我知道 StringBuilders 试图防止发生无意义的内存复制,但与普通串联相比,String.Format 仍然会带来额外的开销。

If we now take an example with a few more strings

如果我们现在再举几个字符串的例子

"a" + rowIndex.ToString() + "b" + colIndex.ToString() + "c" + zIndex.ToString();

we have 6 strings to start with, which will be the same for all cases.
Using concatenation we also have 4 intermediate strings plus the final result. It is those intermediate results that are eliminated by using String,Format (or a StringBuilder).
Remember that to create each intermediate string, the previous one must be copied to a new memory location, it is not just the memory allocation that is potentially slow.

我们有 6 个字符串开始,对于所有情况都是相同的。
使用连接,我们还有 4 个中间字符串加上最终结果。使用 String,Format(或 StringBuilder)消除的是那些中间结果。
请记住,要创建每个中间字符串,必须将前一个字符串复制到新的内存位置,这不仅仅是内存分配可能会变慢。

回答by Andrei R?nea

string.Format is probably a better choice when the format template ("C{0}") is stored in a configuration file (such as Web.config / App.config)

当格式模板(“C{0}”)存储在配置文件(如 Web.config / App.config)中时,string.Format 可能是更好的选择

回答by dviljoen

I did a bit of profiling of various string methods including string.Format, StringBuilder and string concatenation. String concatenation almost always outperformed the other methods of building strings. So, if performance is key, then its better. However, if performance is not critical then I personally find string.Format to be easier to follow in code. (But that's a subjective reason) StringBuilder however, is probably most efficient with respect to memory utilization.

我对各种字符串方法进行了一些分析,包括 string.Format、StringBuilder 和字符串连接。字符串连接几乎总是优于构建字符串的其他方法。所以,如果性能是关键,那么它会更好。但是,如果性能不重要,那么我个人认为 string.Format 在代码中更容易遵循。(但这是一个主观原因)然而,StringBuilder 可能在内存利用率方面是最有效的。