简体   繁体   English

使用StringBuilder获取C#中的常量字符串?

[英]Using StringBuilder for constant strings in C#?

In my current project they put every SQL query in a "QueryList" Class, each of them is a different Get method. 在我当前的项目中,他们将每个SQL查询都放在“ QueryList”类中​​,每个查询都是一个不同的Get方法。 What I don't understand is that they use StringBuilder in these methods to build a constant string, no manipulation or concatenation is used in them. 我不明白的是,它们在这些方法中使用StringBuilder来构建常量字符串,没有在其中使用任何操作或串联。 When I questioned this, they said it was better then using concatenation. 当我对此提出疑问时,他们说,最好使用串联。 To what I know, concatenation of string literals is solved by the compiler, right? 据我所知,字符串文字的串联由编译器解决,对吗? Is there some optimization for this kind of StringBuilder code in the compiler too? 编译器中是否对此类StringBuilder代码进行了优化?

I saw this similar question in Java ( Stringbuilder for Constants ), should be the same for C# ? 我在Java中看到了类似的问题( 用于常量的Stringbuilder ),对于C#是否应该相同?

public static class QueryList
{
    private static StringBuilder GetQuery
    {
        get
        {
            StringBuilder query = new StringBuilder();

            query.Append(" INSERT INTO ");
            query.Append("  MyTable  ");
            query.Append("  (column1, column2)  ");
            query.Append(" VALUES ");
            query.Append("  (@val1 , @val2) ");

            return query;
        }
    }
}

and then in it's called as 然后在其中被称为

string query = QueryList.GetQuery.ToString();

I made some counting and there's ~700 calls to these kind of methods, all followed by a ".ToString();" 我进行了一些计数,大约有700个调用此类方法的方法,所有方法后均带有“ .ToString();”。 I know that when making actual string concatenation it'll be better, but there's only 34 calls that need it. 我知道在进行实际的字符串连接时会更好,但是只有34个需要它的调用。 There's something like 200 queries per seccond by the program. 该程序每秒大约有200个查询。

If you want to return a constant string , just do it: 如果要返回常量 string ,请执行以下操作:

    // I've removed "Get" from the name
    private const string Query = 
      @"INSERT INTO MyTable (
          column1, 
          column2)
        VALUES (
          @val1, 
          @val2)";

there is no need in StringBuilder StringBuilder不需要

Is there some optimization for this kind of StringBuilder code in the compiler 编译器中是否对此类StringBuilder代码进行了一些优化

No. It will run every time. 不。它将每次运行。

There's no perfect way to embed multi-line string literals in C# (unfortunately). 没有完美的方法将多行字符串文字嵌入C#(不幸的是)。 Of the options, this is my favorite for SQL queries: 在这些选项中,这是我最喜欢的SQL查询:

        private static string SomeQuery
        {
            get
            {
                var query = @"
INSERT INTO
MyTable (column1, column2)
values (@val1, @val2)
";
                return query;
            }
        }

There's no optimization here - using the StringBuilder is not only pointless, but actively harmful to the code's efficiency. 这里没有优化-使用StringBuilder不仅毫无意义,而且会严重损害代码的效率。 The property in question will always return the following string: 有问题的属性将始终返回以下字符串:

INSERT INTO   MyTable    (column1, column2)   VALUES   (@val1 , @val2)

That being said, if you're concatenating multiple string literals, any modern C# compiler will realize that it should do that at compile time rather than runtime. 话虽如此,如果您要连接多个字符串文字,那么任何现代C#编译器都将意识到,它应该在编译时而不是在运行时执行。 By way of example, consider the following code: 通过示例,请考虑以下代码:

void Main()
{
    string a = "a" + "b" + "c";
    string b = "def";

    Console.WriteLine(a);
    Console.WriteLine(b);
}

Using LINQpad 5, this compiles to the following IL: 使用LINQpad 5,它将编译为以下IL:

IL_0000:  nop         
IL_0001:  ldstr       "abc"
IL_0006:  stloc.0     // a
IL_0007:  ldstr       "def"
IL_000C:  stloc.1     // b
IL_000D:  ldloc.0     // a
IL_000E:  call        System.Console.WriteLine
IL_0013:  nop         
IL_0014:  ldloc.1     // b
IL_0015:  call        System.Console.WriteLine
IL_001A:  nop         
IL_001B:  ret 

Note in particular that "a" + "b" + "c" and "def" both result in the exact same IL - in other words, the tool is smart enough to realize that "a" + "b" + "c" is exactly the same as "abc" . 特别要注意的是, "a" + "b" + "c""def"都导致完全相同的IL-换句话说,该工具足够聪明,可以意识到"a" + "b" + "c""abc"完全相同。

Now, consider this code: 现在,考虑以下代码:

void Main()
{
    var a = new StringBuilder();
    a.Append("a");
    a.Append("b");
    a.Append("c");
    string b = "def";

    Console.WriteLine(a.ToString());
    Console.WriteLine(b);
}

This translates to the following IL: 这将转换为以下IL:

IL_0000:  nop         
IL_0001:  newobj      System.Text.StringBuilder..ctor
IL_0006:  stloc.0     // a
IL_0007:  ldloc.0     // a
IL_0008:  ldstr       "a"
IL_000D:  callvirt    System.Text.StringBuilder.Append
IL_0012:  pop         
IL_0013:  ldloc.0     // a
IL_0014:  ldstr       "b"
IL_0019:  callvirt    System.Text.StringBuilder.Append
IL_001E:  pop         
IL_001F:  ldloc.0     // a
IL_0020:  ldstr       "c"
IL_0025:  callvirt    System.Text.StringBuilder.Append
IL_002A:  pop         
IL_002B:  ldstr       "def"
IL_0030:  stloc.1     // b
IL_0031:  ldloc.0     // a
IL_0032:  callvirt    System.Object.ToString
IL_0037:  call        System.Console.WriteLine
IL_003C:  nop         
IL_003D:  ldloc.1     // b
IL_003E:  call        System.Console.WriteLine
IL_0043:  nop         
IL_0044:  ret

This is 25 instructions instead of 12 - in other words, the supposedly "better" code actually results in more than twice as much IL and greater memory consumption. 这是25条指令,而不是12条指令-换句话说,所谓的“更好”的代码实际上导致了两倍以上的IL和更大的内存消耗。

That being said, just use a literal const string (as some of the other answers have already pointed out). 话虽如此,只需使用文字const string (正如其他答案中已经指出的那样)。

It's also very strange to return a StringBuilder here unless they intend to add more stuff to the string later. 除非他们打算以后再向字符串中添加更多内容,否则在此处返回StringBuilder也很奇怪。 If they're not doing that, they should just return a string. 如果他们不这样做,则应该返回一个字符串。 Or, in this case, a string constant would be even better, as @David Browne indicated. 或者,在这种情况下,就像@David Browne指出的那样,字符串常量会更好。

This point may be a little more controversial, but making this a property rather than a public constant is kind of pointless and just adds needless overhead. 这一点可能更具争议性,但是将其设置为属性而不是公共常量是没有意义的,并且只会增加不必要的开销。 Properties are ultimately syntactic sugar for method calls, whereas const string allows the compiler to do a text substitution at compile time rather than having to do a runtime method call. 属性最终是方法调用的语法糖,而const string允许编译器在编译时进行文本替换,而不必进行运行时方法调用。

TL;DR Just using a const string is far more efficient because the code shown in your example forces your program to do stuff at runtime that could easily be done at compile time. TL; DR仅使用const string会更有效,因为示例中显示的代码会强制您的程序在运行时执行一些工作,而这些工作可以在编译时轻松完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM