String output: format or concat in C#?

前端 未结 30 1635
一生所求
一生所求 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 11:54

    A week from now Aug 19, 2015, this question will be exactly seven (7) years old. There is now a better way of doing this. Better in terms of maintainability as I haven't done any performance test compared to just concatenating strings (but does it matter these days? a few milliseconds in difference?). The new way of doing it with C# 6.0:

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

    This new feature is better, IMO, and actually better in our case as we have codes where we build querystrings whose values depends on some factors. Imagine one querystring where we have 6 arguments. So instead of doing a, for example:

    var qs = string.Format("q1={0}&q2={1}&q3={2}&q4={3}&q5={4}&q6={5}", 
        someVar, anotherVarWithLongName, var3, var4, var5, var6)
    

    in can be written like this and it's easier to read:

    var qs=$"q1={someVar}&q2={anotherVarWithLongName}&q3={var3}&q4={var4}&q5={var5}&q6={var6}";
    
    0 讨论(0)
  • 2020-11-22 11:57

    Strings are immutable, this means the same tiny piece of memory is used over and over in your code. Adding the same two strings together and creating the same new string over and over again doesn't impact memory. .Net is smart enough just to use the same memory reference. Therefore your code doesn't truly test the difference between the two concat methods.

    Try this on for size:

    Stopwatch s = new Stopwatch();
    
    int n = 1000000;
    long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0, sbElapsedMilliseconds = 0, sbElapsedTicks = 0;
    
    Random random = new Random(DateTime.Now.Millisecond);
    
    string result;
    s.Start();
    for (var i = 0; i < n; i++)
        result = (random.Next().ToString() + " " + random.Next().ToString());
    s.Stop();
    cElapsedMilliseconds = s.ElapsedMilliseconds;
    cElapsedTicks = s.ElapsedTicks;
    s.Reset();
    
    s.Start();
    for (var i = 0; i < n; i++)
        result = string.Format("{0} {1}", random.Next().ToString(), random.Next().ToString());
    s.Stop();
    fElapsedMilliseconds = s.ElapsedMilliseconds;
    fElapsedTicks = s.ElapsedTicks;
    s.Reset();
    
    StringBuilder sb = new StringBuilder();
    s.Start();
    for(var i = 0; i < n; i++){
        sb.Clear();
        sb.Append(random.Next().ToString());
        sb.Append(" ");
        sb.Append(random.Next().ToString());
        result = sb.ToString();
    }
    s.Stop();
    sbElapsedMilliseconds = s.ElapsedMilliseconds;
    sbElapsedTicks = s.ElapsedTicks;
    s.Reset();
    
    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");
    Console.WriteLine(n.ToString() + " x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(\" \"); sb.Append(random.Next().ToString()); result = sb.ToString(); took: " + (sbElapsedMilliseconds) + "ms - " + (sbElapsedTicks) + " ticks");
    Console.WriteLine("****************");
    Console.WriteLine("Press Enter to Quit");
    Console.ReadLine();
    

    Sample Output:

    1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 513ms - 1499816 ticks
    1000000 x result = (p.FirstName + " " + p.LastName); took: 393ms - 1150148 ticks
    1000000 x sb.Clear();sb.Append(random.Next().ToString()); sb.Append(" "); sb.Append(random.Next().ToString()); result = sb.ToString(); took: 405ms - 1185816 ticks
    
    0 讨论(0)
  • 2020-11-22 11:57

    According to the MCSD prep material, Microsoft suggests using the + operator when dealing with a very small number of concatenations (probably 2 to 4). I'm still not sure why, but it's something to consider.

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

    Nice one!

    Just added

            s.Start();
            for (var i = 0; i < n; i++)
                result = string.Concat(p.FirstName, " ", p.LastName);
            s.Stop();
            ceElapsedMilliseconds = s.ElapsedMilliseconds;
            ceElapsedTicks = s.ElapsedTicks;
            s.Reset();
    

    And it is even faster (I guess string.Concat is called in both examples, but the first one requires some sort of translation).

    1000000 x result = string.Format("{0} {1}", p.FirstName, p.LastName); took: 249ms - 3571621 ticks
    1000000 x result = (p.FirstName + " " + p.LastName); took: 65ms - 944948 ticks
    1000000 x result = string.Concat(p.FirstName, " ", p.LastName); took: 54ms - 780524 ticks
    
    0 讨论(0)
  • 2020-11-22 12:00

    Pity the poor translators

    If you know your application will stay in English, then fine, save the clock ticks. However, many cultures would usually see Lastname Firstname in, for instance, addresses.

    So use string.Format(), especially if you're going to ever have your application go anywhere that English is not the first language.

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

    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.

    0 讨论(0)
提交回复
热议问题