字符串输出:C#格式或concat?

字符串输出:C#格式或concat?,c#,string,coding-style,string.format,C#,String,Coding Style,String.format,假设您想要输出或压缩字符串。您喜欢以下哪种款式 var p=new{FirstName=“Bill”,LastName=“Gates”} Console.WriteLine(“{0}{1}”,p.FirstName,p.LastName) Console.WriteLine(p.FirstName+“”+p.LastName) 您是更喜欢使用格式还是只使用concat字符串?你最喜欢什么?其中一个会伤到你的眼睛吗 你有没有合理的理由使用其中一个而不是另一个 我会选择第二个。就我个人而言,第二

假设您想要输出或压缩字符串。您喜欢以下哪种款式

  • var p=new{FirstName=“Bill”,LastName=“Gates”}

  • Console.WriteLine(“{0}{1}”,p.FirstName,p.LastName)

  • Console.WriteLine(p.FirstName+“”+p.LastName)

您是更喜欢使用格式还是只使用concat字符串?你最喜欢什么?其中一个会伤到你的眼睛吗

你有没有合理的理由使用其中一个而不是另一个


我会选择第二个。

就我个人而言,第二个是因为您使用的所有东西都是按直接顺序输出的。而对于第一个变量,您必须将{0}和{1}与适当的var相匹配,这很容易出错

<>至少它不如C++ SpaveTF那么坏,如果你得到变量类型错误,整个事情就会爆炸。
另外,由于第二个是内联的,它不必对所有{0}事物进行任何搜索和替换,因此后者应该更快。。。虽然我不确定。

我认为这在很大程度上取决于输出的复杂程度。我倾向于选择当时效果最好的方案


根据作业选择正确的工具:D,以看起来最干净的为准

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


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

我也喜欢第二个,但目前我没有支持该位置的合理参数。

通常我更喜欢前者,尤其是当字符串变长时,它更容易阅读

我认为另一个好处是性能,因为后者在将最后一个字符串传递给Console.Write方法之前实际上执行了两个字符串创建语句。Format在封面下使用了StringBuilder,因此避免了多次连接


但是,应该注意的是,如果传递给String.Format(以及其他类似于Console.Write的方法)的参数是值类型,那么它们在传递之前将被装箱,这可以提供其自身的性能影响

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

格式保存了大量的引号和加号

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

虽然只保存了几个字符,但我认为,在本例中,格式使其更加清晰。

在这样一个简单的场景中,连接字符串是很好的-任何比这更复杂的东西都更复杂,即使是LastName,FirstName。使用这种格式,您可以一目了然地看到在读取代码时字符串的最终结构是什么,通过串联,几乎不可能立即识别最终结果(除了像这样一个非常简单的示例)

从长远来看,这意味着,当您回来更改字符串格式时,您将能够弹出并对格式字符串进行一些调整,或者皱起眉头,开始在混合了文本的各种属性访问器之间移动,这更可能带来问题

如果您使用的是.NET 3.5,则可以使用扩展方法,并获得一种简单流畅的即兴语法,如下所示:

string str = "{0} {1} is my friend. {3}, {2} is my boss.".FormatWith(prop1,prop2,prop3,prop4);
最后,随着应用程序复杂性的增加,您可能会决定,要在应用程序中合理地维护字符串,您需要将它们移动到资源文件中以进行本地化,或者只是移动到静态帮助器中。如果您一直使用格式,那么这将更容易实现,并且您的代码可以非常简单地进行重构以使用

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

实际上,我喜欢第一个,因为当文本中有很多变量时,我似乎更容易阅读。另外,使用string.Format(),呃,Format时更容易处理引号。下面是字符串连接的示例

  • 格式化是“.NET”的方式。某些重构工具(例如Refactor!)甚至会建议重构concat样式代码以使用格式化样式
  • 对于编译器来说,格式化更容易优化(尽管第二个可能会被重构以使用“Concat”方法,该方法速度很快)
  • 格式通常更清晰易读(特别是使用“奇特”的格式)
  • 格式化意味着对所有变量隐式调用“.ToString”,这有利于可读性
  • 根据“有效C#”的说法,.NET的“WriteLine”和“Format”实现混乱不堪,它们自动装箱所有的值类型(这很糟糕)。“有效C#”建议显式执行“.ToString”调用,IMHO认为这是假的(请参阅)
  • 目前,编译器未检查格式化类型提示,导致运行时错误。但是,这可以在将来的版本中进行修改

  • 虽然我完全理解风格偏好,并在我的第一个答案中选择了连接,部分是基于我自己的偏好,但我的部分决定是基于连接会更快的想法。因此,出于好奇,我对它进行了测试,结果令人震惊,尤其是对于这样一根小绳子

    使用以下代码:

        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");
    
    我得到了以下结果:

    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
    

    使用格式化方法的速度要慢100多倍!!连接甚至没有注册为1ms,这就是为什么我也会输出计时器的节拍。

    我会使用String.Format,但我也会在资源文件中使用Format字符串,这样它就可以被其他语言本地化。使用简单的字符串concat不允许这样做。显然,如果您不需要对该字符串进行本地化,那么就没有理由考虑这个问题。这真的取决于我使用的字符串
    Console.WriteLine(String.Concat(p.FirstName," ",p.LastName));
    
    Bill Gates
    Console.WriteLine(p.FirstName + " " + p.LastName); took: 8ms - 30488 ticks
    Bill Gates
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took: 0ms - 182 ticks
    
    Bill Gates
    Console.WriteLine(FirstName + " " + LastName); took: 5ms - 20335 ticks
    Bill Gates
    Console.WriteLine(FirstName + " " + LastName); took: 0ms - 156 ticks
    Bill Gates
    Console.WriteLine(FirstName + " " + LastName); took: 0ms - 122 ticks
    Bill Gates
    Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 181 ticks
    Bill Gates
    Console.WriteLine("{0} {1}", FirstName, LastName); took: 0ms - 122 ticks
    Bill Gates
    String.Concat(FirstName, " ", LastName); took: 0ms - 142 ticks
    Bill Gates
    String.Concat(FirstName, " ", LastName); took: 0ms - 117 ticks
    
    Console.WriteLine("{0} {1}", p.FirstName, p.LastName); took (avg): 0ms - 689 ticks
    Console.WriteLine(p.FirstName + " " + p.LastName); took (avg): 0ms - 683 ticks
    
    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");
    
    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);
    
            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();
    
    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
    
    class Program {
       static void Main(string[] args) {
    
          var p = new { FirstName = "Bill", LastName = "Gates" };
    
          var tests = new[] {
             new { Name = "Concat", Action = new Action(delegate() { string x = p.FirstName + " " + p.LastName; }) },
             new { Name = "Format", Action = new Action(delegate() { string x = string.Format("{0} {1}", p.FirstName, p.LastName); }) },
             new { Name = "StringBuilder", Action = new Action(delegate() {
                StringBuilder sb = new StringBuilder();
                sb.Append(p.FirstName);
                sb.Append(" ");
                sb.Append(p.LastName);
                string x = sb.ToString();
             }) }
          };
    
          var Watch = new Stopwatch();
          foreach (var t in tests) {
             for (int i = 0; i < 5; i++) {
                Watch.Reset();
                long Elapsed = ElapsedTicks(t.Action, Watch, 10000);
                Console.WriteLine(string.Format("{0}: {1} ticks", t.Name, Elapsed.ToString()));
             }
          }
       }
    
       public static long ElapsedTicks(Action ActionDelg, Stopwatch Watch, int Iterations) {
          Watch.Start();
          for (int i = 0; i < Iterations; i++) {
             ActionDelg();
          }
          Watch.Stop();
          return Watch.ElapsedTicks / Iterations;
       }
    }
    
    Concat: 406 ticks Concat: 356 ticks Concat: 411 ticks Concat: 299 ticks Concat: 266 ticks Format: 5269 ticks Format: 954 ticks Format: 1004 ticks Format: 984 ticks Format: 974 ticks StringBuilder: 629 ticks StringBuilder: 484 ticks StringBuilder: 482 ticks StringBuilder: 508 ticks StringBuilder: 504 ticks
    Console.WriteLine("User {0} accessed {1} on {2}.", 
                       user.Name, fileName, timestamp);
    
    Console.WriteLine("User " + user.Name + " accessed " + fileName + 
                      " on " + timestamp + ".");
    
       Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
    
       Console.WriteLine(p.FirstName + " " + p.LastName);
    
    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();
    
    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
    
    string s = a + "foo" + b;
    
    string tmp1 = a;
    string tmp2 = "foo" 
    string tmp3 = concat(tmp1, tmp2);
    string tmp4 = b;
    string s = concat(tmp3, tmp4);
    
    var name = "Bill";
    var surname = "Gates";
    MessageBox.Show($"Welcome to the show, {name} {surname}!");
    
    var p = new { FirstName = "Bill", LastName = "Gates" };
    var fullname = $"{p.FirstName} {p.LastName}";
    
    var qs = string.Format("q1={0}&q2={1}&q3={2}&q4={3}&q5={4}&q6={5}", 
        someVar, anotherVarWithLongName, var3, var4, var5, var6)
    
    var qs=$"q1={someVar}&q2={anotherVarWithLongName}&q3={var3}&q4={var4}&q5={var5}&q6={var6}";