字符串输出:C# 中的格式或连接?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16432/
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-01 08:53:00  来源:igfitidea点击:

String output: format or concat in C#?

提问by Philippe

Let's say that you want to output or concat strings. Which of the following styles do you prefer?

假设您想输出或连接字符串。您更喜欢以下哪种风格?

  • var p = new { FirstName = "Bill", LastName = "Gates" };

  • Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

  • Console.WriteLine(p.FirstName + " " + p.LastName);

  • var p = new { FirstName = "Bill", LastName = "Gates" };

  • Console.WriteLine("{0} {1}", p.FirstName, p.LastName);

  • Console.WriteLine(p.FirstName + " " + p.LastName);

Do you rather use format or do you simply concat strings? What is your favorite? Is one of these hurting your eyes?

你更喜欢使用格式还是简单地连接字符串?什么是你最喜欢的?其中之一是否会伤害您的眼睛?

Do you have any rational arguments to use one and not the other?

你有任何合理的论据来使用一种而不是另一种吗?

I'd go for the second one.

我会去第二个。

采纳答案by Micha? Piaskowski

Try this code.

试试这个代码。

It's a slightly modified version of your code.
1. I removed Console.WriteLine as it's probably few orders of magnitude slower than what I'm trying to measure.
2. I'm starting the Stopwatch before the loop and stopping it right after, this way I'm not losing precision if the function takes for example 26.4 ticks to execute.
3. The way you divided the result by some iterations was wrong. See what happens if you have 1000 milliseconds and 100 milliseconds. In both situations, you will get 0 ms after dividing it by 1000000.

这是对您的代码稍加修改的版本。
1. 我删除了 Console.WriteLine,因为它可能比我试图测量的慢几个数量级。
2. 我在循环之前启动秒表并在循环之后立即停止,这样如果函数需要例如 26.4 个滴答来执行,我不会失去精度。
3. 你把结果除以一些迭代的方式是错误的。看看如果你有 1000 毫秒和 100 毫秒会发生什么。在这两种情况下,除以 1000000 后都会得到 0 毫秒。

Stopwatch s = new Stopwatch();

var p = new { FirstName = "Bill", LastName = "Gates" };

int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;

string result;
s.Start();
for (var i = 0; i < n; i++)
    result = (p.FirstName + " " + p.LastName);
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();
s.Start();
for (var i = 0; i < n; i++)
    result = string.Format("{0} {1}", p.FirstName, p.LastName);
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();


Console.Clear();
Console.WriteLine(n.ToString()+" x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
Thread.Sleep(4000);

Those are my results:

这些是我的结果:

1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 618ms - 2213706 ticks
1000000 x result = (p.FirstName + " " + p.LastName); took: 166ms - 595610 ticks

1000000 x 结果 = string.Format("{0} {1}", p.FirstName, p.LastName); 花费:618ms - 2213706 滴答
1000000 x 结果 = (p.FirstName + " " + p.LastName); 耗时:166 毫秒 - 595610 滴答

回答by Adam Haile

Personally, the second one as everything you are using is in the direct order it will be output in. Whereas with the first you have to match up the {0} and {1} with the proper var, which is easy to mess up.

就个人而言,第二个作为您正在使用的所有内容的直接输出顺序。而第一个您必须将 {0} 和 {1} 与正确的 var 匹配,这很容易搞砸。

At least it's not as bad as the C++ sprintf where if you get the variable type wrong the whole thing will blow up.

至少它不像 C++ sprintf 那样糟糕,如果你把变量类型弄错了,整个事情就会爆炸。

Also, since the second is all inline and it doesn't have to do any searching and replacing for all the {0} things, the latter should be faster... though I don't know for sure.

此外,由于第二个都是内联的,它不必对所有 {0} 事物进行任何搜索和替换,后者应该更快......尽管我不确定。

回答by mercutio

I think this depends heavily on how complex the output is. I tend to choose whichever scenario works best at the time.

我认为这在很大程度上取决于输出的复杂程度。我倾向于选择当时最有效的场景。

Pick the right tool based on the job :D Whichever looks cleanest!

根据工作选择正确的工具 :D 哪个看起来最干净!

回答by mercutio

For very simple manipulation I'd use concatenation, but once you get beyond 2 or 3 elements Format becomes more appropriate IMO.

对于非常简单的操作,我会使用串联,但是一旦超过 2 或 3 个元素,格式就变得更合适 IMO。

Another reason to prefer String.Format is that .NET strings are immutable and doing it this way creates fewer temporary/intermediate copies.

另一个喜欢 String.Format 的原因是 .NET 字符串是不可变的,这样做会创建更少的临时/中间副本。

回答by Chuck

I prefer the second as well but I have no rational arguments at this time to support that position.

我也更喜欢第二个,但目前我没有理性的论据来支持这个立场。

回答by samjudson

Generally I prefer the former, as especially when the strings get long it can be much easier to read.

通常我更喜欢前者,特别是当字符串变长时,它会更容易阅读。

The other benefit is I believe one of performance, as the latter actually performs 2 string creation statements before passing the final string to the Console.Write method. String.Format uses a StringBuilder under the covers I believe, so multiple concatenations are avoided.

另一个好处是我相信性能之一,因为后者在将最终字符串传递给 Console.Write 方法之前实际上执行了 2 个字符串创建语句。我相信 String.Format 在幕后使用了 StringBuilder,因此避免了多个串联。

It should be noted however that if the parameters you are passing in to String.Format (and other such methods like Console.Write) are value types then they will be boxed before passed in, which can provide its own performance hits. Blog post on this here.

然而,应该注意的是,如果您传递给 String.Format(以及其他诸如 Console.Write 之类的方法)的参数是值类型,那么它们将在传入之前被装箱,这可以提供自己的性能命中。关于这个的博客文章在这里

回答by Mike

For basic string concatenation, I generally use the second style - easier to read and simpler. However, if I am doing a more complicated string combination I usually opt for String.Format.

对于基本的字符串连接,我通常使用第二种风格——更容易阅读和更简单。但是,如果我要进行更复杂的字符串组合,我通常会选择 String.Format。

String.Format saves on lots of quotes and pluses...

String.Format 节省了大量的引号和加号...

Console.WriteLine("User {0} accessed {1} on {2}.", user.Name, fileName, timestamp);
vs
Console.WriteLine("User " + user.Name + " accessed " + fileName + " on " + timestamp + ".");

Only a few charicters saved, but I think, in this example, format makes it much cleaner.

只保存了几个字符,但我认为,在这个例子中,格式使它更清晰。

回答by Nathan

Concatenating strings is fine in a simple scenario like that - it is more complicated with anything more complicated than that, even LastName, FirstName. With the format you can see, at a glance, what the final structure of the string will be when reading the code, with concatenation it becomes almost impossible to immediately discern the final result (except with a very simple example like this one).

在像这样的简单场景中连接字符串很好 - 比这更复杂的东西更复杂,甚至姓氏,名字。通过这种格式,您可以在阅读代码时一目了然地看到字符串的最终结构,通过连接几乎不可能立即辨别最终结果(除了像这样的一个非常简单的例子)。

What that means in the long run is that when you come back to make a change to your string format, you will either have the ability to pop in and make a few adjustments to the format string, or wrinkle your brow and start moving around all kinds of property accessors mixed with text, which is more likely to introduce problems.

从长远来看,这意味着当您回来对字符串格式进行更改时,您将能够弹出并对格式字符串进行一些调整,或者皱眉并开始四处走动与文本混合的各种属性访问器,这更容易引入问题。

If you're using .NET 3.5 you can use an extension method like this oneand get an easy flowing, off the cuff syntax like this:

如果您使用的是 .NET 3.5,您可以使用像这样的扩展方法,并获得一种轻松流畅的无袖语法,如下所示:

string str = "{0} {1} is my friend. {3}, {2} is my boss.".FormatWith(prop1,prop2,prop3,prop4);

Finally, as your application grows in complexity you may decide that to sanely maintain strings in your application you want to move them into a resource file to localize or simply into a static helper. This will be MUCH easier to achieve if you have consistently used formats, and your code can be quite simply refactored to use something like

最后,随着您的应用程序变得越来越复杂,您可能会决定,为了在您的应用程序中合理维护字符串,您希望将它们移动到资源文件中以进行本地化或简单地移动到静态帮助程序中。如果您一直使用格式,这将更容易实现,并且您的代码可以非常简单地重构为使用类似

string name = String.Format(ApplicationStrings.General.InformalUserNameFormat,this.FirstName,this.LastName);

回答by adparadox

I actually like the first one because when there are a lot of variables intermingled with the text it seems easier to read to me. Plus, it is easier to deal with quotes when using the string.Format(), uh, format. Here is decent analysisof string concatenation.

我实际上喜欢第一个,因为当有很多变量与文本混合时,对我来说似乎更容易阅读。另外,使用 string.Format(),呃,格式时更容易处理引号。这是对字符串连接的体面分析

回答by Konrad Rudolph

  1. Formatting is the “.NET” way of doing it. Certain refactoring tools (Refactor! for one) will even propose to refactor the concat-style code to use the formatting style.
  2. Formatting is easier to optimize for the compiler (although the second will probably be refactored to use the 'Concat' method which is fast).
  3. Formatting is usually clearer to read (especially with “fancy” formatting).
  4. Formatting means implicit calls to '.ToString' on all variables, which is good for readability.
  5. According to “Effective C#”, the .NET 'WriteLine' and 'Format' implementations are messed up, they autobox all value types (which is bad). “Effective C#” advises to perform '.ToString' calls explicitly, which IMHO is bogus (see Jeff's posting)
  6. At the moment, formatting type hints are not checked by the compiler, resulting in runtime errors. However, this could be amended in future versions.
  1. 格式化是“.NET”的方式。某些重构工具(Refactor! for one)甚至会建议重构 concat 风格的代码以使用格式化风格。
  2. 格式化更容易为编译器优化(尽管第二个可能会被重构以使用快速的“Concat”方法)。
  3. 格式通常更清晰易读(尤其是“花哨的”格式)。
  4. 格式化意味着对所有变量隐式调用'.ToString',这有利于可读性。
  5. 根据“Effective C#”,.NET 'WriteLine' 和 'Format' 实现搞砸了,它们自动装箱所有值类型(这很糟糕)。“Effective C#” 建议显式执行 '.ToString' 调用,恕我直言是假的(请参阅Jeff 的帖子
  6. 目前,编译器不会检查格式化类型提示,从而导致运行时错误。但是,这可能会在未来的版本中进行修改。

回答by Adam Haile

While I totally understand the style preference and picked concatenation for my first answer partly based on my own preference, part of my decision was based on the thought that concatenation would be faster. So, out of curiosity, I tested it and the results were staggering, especially for such a small string.

虽然我完全理解样式偏好并选择串联作为我的第一个答案,部分是基于我自己的偏好,但我的决定的一部分是基于串联会更快的想法。因此,出于好奇,我对其进行了测试,结果令人震惊,尤其是对于这么小的字符串。

Using the following code:

使用以下代码:

    System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();

    var p = new { FirstName = "Bill", LastName = "Gates" };

    s.Start();
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    s.Stop();
    Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

    s.Reset();
    s.Start();
    Console.WriteLine(p.FirstName + " " + p.LastName);
    s.Stop();

    Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took: " + s.ElapsedMilliseconds + "ms - " + s.ElapsedTicks + " ticks");

I got the following results:

我得到了以下结果:

Bill Gates
Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 2ms - 7280 ticks
Bill Gates
Console.WriteLine(p.FirstName + " " + p.LastName); took: 0ms - 67 ticks

Using the formatting method is over 100 times slower!! Concatenation didn't even register as 1ms, which is why I output the timer ticks as well.

使用格式化方法要慢 100 多倍!!连接甚至没有注册为 1ms,这就是为什么我也输出计时器滴答声的原因。