String output: format or concat in C#?

前端 未结 30 1616
一生所求
一生所求 2020-11-22 11:40

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 = \"Ga

相关标签:
30条回答
  • 2020-11-22 12:11

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

    0 讨论(0)
  • 2020-11-22 12:12

    I choose based on readability. I prefer the format option when there's some text around the variables. In this example:

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

    you understand the meaning even without variable names, whereas the concat is cluttered with quotes and + signs and confuses my eyes:

    Console.WriteLine("User " + user.Name + " accessed " + fileName + 
                      " on " + timestamp + ".");
    

    (I borrowed Mike's example because I like it)

    If the format string doesn't mean much without variable names, I have to use concat:

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

    The format option makes me read the variable names and map them to the corresponding numbers. The concat option doesn't require that. I'm still confused by the quotes and + signs, but the alternative is worse. Ruby?

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

    Performance wise, I expect the format option to be slower then the concat, since format requires the string to be parsed. I don't remember having to optimize this kind of instruction, but if I did, I'd look at string methods like Concat() and Join().

    The other advantage with format is that the format string can be put in a configuration file. Very handy with error messages and UI text.

    0 讨论(0)
  • 2020-11-22 12:13

    Here are my results over 100,000 iterations:

    Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took (avg): 0ms - 689 ticks
    Console.WriteLine(p.FirstName + " " + p.LastName); took (avg): 0ms - 683 ticks
    

    And here is the bench code:

    Stopwatch s = new Stopwatch();
    
    var p = new { FirstName = "Bill", LastName = "Gates" };
    
    //First print to remove the initial cost
    Console.WriteLine(p.FirstName + " " + p.LastName);
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    
    int n = 100000;
    long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;
    
    for (var i = 0; i < n; i++)
    {
        s.Start();
        Console.WriteLine(p.FirstName + " " + p.LastName);
        s.Stop();
        cElapsedMilliseconds += s.ElapsedMilliseconds;
        cElapsedTicks += s.ElapsedTicks;
        s.Reset();
        s.Start();
        Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
        s.Stop();
        fElapsedMilliseconds += s.ElapsedMilliseconds;
        fElapsedTicks += s.ElapsedTicks;
        s.Reset();
    }
    
    Console.Clear();
    
    Console.WriteLine("Console.WriteLine(\"{0} {1}\", p.FirstName, p.LastName); took (avg): " + (fElapsedMilliseconds / n) + "ms - " + (fElapsedTicks / n) + " ticks");
    Console.WriteLine("Console.WriteLine(p.FirstName + \" \" + p.LastName); took (avg): " + (cElapsedMilliseconds / n) + "ms - " + (cElapsedTicks / n) + " ticks");
    

    So, I don't know whose reply to mark as an answer :)

    0 讨论(0)
  • 2020-11-22 12:14

    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.

    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.

    0 讨论(0)
  • 2020-11-22 12:15

    Starting from C# 6.0 interpolated strings can be used to do this, which simplifies the format even more.

    var name = "Bill";
    var surname = "Gates";
    MessageBox.Show($"Welcome to the show, {name} {surname}!");
    

    An interpolated string expression looks like a template string that contains expressions. An interpolated string expression creates a string by replacing the contained expressions with the ToString represenations of the expressions’ results.

    Interpolated strings have similar performance to String.Format, but improved readability and shorter syntax, due to the fact that values and expressions are inserted in-line.

    Please also refer to this dotnetperls article on string interpolation.

    If you are looking for a default way to format your strings, this makes sense in terms of readability and performance (except if microseconds is going to make a difference in your specific use case).

    0 讨论(0)
  • 2020-11-22 12:15
    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.
    0 讨论(0)
提交回复
热议问题