Mehrzeiliges Zeichenfolgenliteral in C #


1046

Gibt es eine einfache Möglichkeit, ein mehrzeiliges Zeichenfolgenliteral in C # zu erstellen?

Folgendes habe ich jetzt:

string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";

Ich weiß, dass PHP hat

<<<BLOCK

BLOCK;

Hat C # etwas Ähnliches?


1
In Ihrem Beispiel gibt es keine Zeilenumbrüche. Willst du sie?
Weiqure

8
Nein. Ich wollte aus Gründen der Sichtbarkeit / Code-Sauberkeit nur mehrere Zeilen.
Chet

6
In diesem Fall enthalten wörtliche Zeichenfolgen die Zeilenumbrüche. Sie können @ "..." verwenden. Ersetzen Sie (Environment.NewLine, ""), wenn Sie möchten.
Weiqure

9
Sie sollten in Betracht ziehen, das 42als Parameter zu binden , insbesondere wenn es aus Benutzereingaben stammt, um eine SQL-Injection zu vermeiden.
Jens Mühlenhoff

@ JensMühlenhoff Wie wird jemand eine fest codierte Zeichenfolge einfügen, die im Code definiert ist?
Mr. Boy

Antworten:


1590

Sie können das @Symbol vor a verwenden string, um ein wörtliches Zeichenfolgenliteral zu bilden :

string query = @"SELECT foo, bar
FROM table
WHERE id = 42";

Sie müssen bei dieser Methode auch keine Sonderzeichen maskieren, außer bei doppelten Anführungszeichen, wie in Jon Skeets Antwort gezeigt.


43
Es ist sowieso ein String-Literal - es ist ein wörtliches String-Literal mit dem @ -Zeichen.
Jon Skeet

95
Wenn Ihre Zeichenfolge doppelte Anführungszeichen (") enthält, können Sie diese wie folgt maskieren:" "(das sind zwei doppelte Anführungszeichen)
Muad'Dib

8
Gibt es eine Möglichkeit, das oben genannte zu tun, ohne neue Linien zu erstellen? Ich habe einen wirklich langen Text, den ich gerne in der IDE sehen würde, ohne das Pluszeichen ("hi" + "there") verwenden zu müssen.
Noelicus

2
@noelicus - nicht wirklich, aber Sie könnten das umgehen, indem Sie die Technik von Weiqure oben verwenden von:@"my string".Replace(Environment.NewLine, "")
John Rasch

8
@afsharm Sie können $ @ "Text" verwenden
Patrick McDonald

566

Es wird in C # als wörtliches Zeichenfolgenliteral bezeichnet , und es geht nur darum, @ vor das Literal zu setzen. Dies ermöglicht nicht nur mehrere Zeilen, sondern deaktiviert auch das Escapezeichen. So können Sie zum Beispiel Folgendes tun:

string query = @"SELECT foo, bar
FROM table
WHERE name = 'a\b'";

Dies schließt jedoch die Zeilenumbrüche (unter Verwendung der Zeilenumbrüche, unter denen Ihre Quelle sie hat) in die Zeichenfolge ein. Für SQL ist dies nicht nur harmlos, sondern verbessert wahrscheinlich die Lesbarkeit überall dort, wo Sie die Zeichenfolge sehen. An anderen Stellen ist dies möglicherweise nicht erforderlich. In diesem Fall müssen Sie entweder kein mehrzeiliges wörtliches Zeichenfolgenliteral verwenden. oder entfernen Sie sie aus der resultierenden Zeichenfolge.

Das einzige Problem ist, dass Sie, wenn Sie ein doppeltes Anführungszeichen wünschen, ein zusätzliches doppeltes Anführungszeichen hinzufügen müssen:

string quote = @"Jon said, ""This will work,"" - and it did!";

2
Diese Antwort ist falsch; Es werden neue Zeilen eingeführt, die OP nicht wünscht.
TamaMcGlinn

@TamaMcGlinn: Ich werde der Antwort etwas hinzufügen - es war nicht klar, wann das OP die Frage schrieb.
Jon Skeet

105

Das Problem bei der Verwendung von Zeichenfolgenliteral ist, dass Ihr Code dadurch etwas " seltsam " aussehen kann, da er vollständig linksbündig ausgerichtet werden muss, um keine Leerzeichen in der Zeichenfolge selbst zu erhalten:

    var someString = @"The
quick
brown
fox...";

Yuck.

Die Lösung, die ich gerne verwende und die alles gut auf den Rest Ihres Codes abstimmt, lautet:

var someString = String.Join(
    Environment.NewLine,
    "The",
    "quick",
    "brown",
    "fox...");

Und natürlich, wenn Sie nur logisch Linien wollen aufzuspalten einer SQL - Anweisung , wie Sie sind und nicht wirklich eine neue Linie benötigen, können Sie immer nur Ersatz Environment.NewLinefür " ".


2
Viel sauberer, danke. Auch String.Concat funktioniert ähnlich und benötigt kein Trennzeichen.
Seth

Vielen Dank. Ich mag den String.Join mit dem Trennzeichen "" für SQL, da er Einrückungen / Paren-Matching ermöglicht und das Hinzufügen des führenden Leerzeichens vermeidet.
Rob bei TVSeries.com

7
Die erste Version ist zwar hässlich, erfordert jedoch keinen Code zum Ausführen . Die zweite Option hat offensichtlich einen Laufzeitaufwand, um die separaten Zeichenfolgen zu verketten.
Gone Coding

@GoneCoding, bist du dir da sicher? Der Compiler kann die Verkettung optimieren.
William Jockusch

@WilliamJockusch: Im Allgemeinen bleiben Funktionsaufrufe ohne Operator (wie Join) erhalten und werden nicht optimiert. Am besten überprüfen Sie den kompilierten Code, aber ich würde Geld legen, dass der Anruf nicht optimiert ist.
Gone Coding

104

Ein weiteres Problem, auf das Sie achten sollten, ist die Verwendung von String-Literalen in string.Format. In diesem Fall müssen Sie geschweifte Klammern / Klammern '{' und '}' umgehen.

// this would give a format exception
string.Format(@"<script> function test(x) 
      { return x * {0} } </script>", aMagicValue)
// this contrived example would work
string.Format(@"<script> function test(x) 
      {{ return x * {0} }} </script>", aMagicValue)

14
Und welchen Unterschied macht es? Mit oder ohne "@" müssen Sie "{{" verdoppeln, um "{" als druckbares Zeichen zu erhalten. Es geht um String.Format, nicht um String-Inhalt.
Greenoldman

12
Es ist ein bemerkenswertes Problem für Leute, die Javascript-Code in eine Zeichenfolge einfügen möchten, was in wörtlichen Zeichenfolgenliteralen häufiger vorkommt als in normalen Zeichenfolgen.
Ed Brannin

2
In der neuen C # 6.0 können Sie einen indizierten Eigenschaftsoperator zusammen mit dem wörtlichen Zeichenfolgenliteral verwenden (wie folgt $ @ "Wert ist {this.Value}";)
Heliac

2
@Heliac Ich denke, Sie meinen, interpolierte Zeichenfolgen können mit dieser Syntax auch wörtlich sein. var query = $ @ "wähle foo, Balken aus Tabelle, wobei id = {id}";
Brian

102

Als Randnotiz können Sie mit C # 6.0 jetzt interpolierte Zeichenfolgen mit dem wörtlichen Zeichenfolgenliteral kombinieren:

string camlCondition = $@"
<Where>
    <Contains>
        <FieldRef Name='Resource'/>
        <Value Type='Text'>{(string)parameter}</Value>
    </Contains>
</Where>";

10
Cool, das wusste ich bis jetzt nicht. Wenn jemand interessiert ist: Das $ thingy heißt "Interpolated Strings" und Sie können es hier ausführlich lesen: msdn.microsoft.com/en-us/library/dn961160.aspx
Hauke ​​P.


1
Ich gehe davon aus, dass eine wörtliche geschweifte Klammer dann verdoppelt werden muss, z. B. $@"{{example literal text { fooString }. }}" Dies kann einige verwirren, da Angular, React und Vue.js die entgegengesetzte Konvention verwenden.
Patrick Szalapski

58

Warum verwechseln die Leute Strings immer wieder mit String-Literalen? Die akzeptierte Antwort ist eine großartige Antwort auf eine andere Frage. nicht zu diesem.

Ich weiß, dass dies ein altes Thema ist, aber ich bin mit möglicherweise der gleichen Frage wie das OP hierher gekommen, und es ist frustrierend zu sehen, wie die Leute es immer wieder falsch lesen. Oder vielleicht verstehe ich es falsch, ich weiß es nicht.

Grob gesagt ist eine Zeichenfolge ein Bereich des Computerspeichers, der während der Ausführung eines Programms eine Folge von Bytes enthält, die Textzeichen zugeordnet werden können. Ein Zeichenfolgenliteral hingegen ist ein noch nicht kompilierter Quellcode, der den Wert darstellt, der zum späteren Initialisieren einer Zeichenfolge während der Ausführung des Programms verwendet wird, in dem sie angezeigt wird.

In C # ist die Anweisung ...

 string query = "SELECT foo, bar"
 + " FROM table"
 + " WHERE id = 42";

... erzeugt keinen dreizeiligen String, sondern einen Einzeiler; die Verkettung von drei Zeichenfolgen (jede aus einem anderen Literal initialisiert), von denen keine einen Modifikator für neue Zeilen enthält.

Was das OP zu fragen scheint - zumindest was ich mit diesen Worten fragen würde - ist nicht, wie man in die kompilierte Zeichenfolge Zeilenumbrüche einführt, die die im Quellcode gefundenen nachahmen, sondern wie man aus Gründen der Klarheit lange aufbricht , einzelne Textzeile im Quellcode ohne Unterbrechungen in der kompilierten Zeichenfolge. Und ohne eine längere Ausführungszeit zu benötigen, müssen Sie die mehreren Teilzeichenfolgen aus dem Quellcode zusammenfügen. Wie die nachfolgenden Backslashes in einem mehrzeiligen String-Literal in Javascript oder C ++.

Wenn ich die Verwendung von wörtlichen Zeichenfolgen, Neverminds StringBuilder, String.JoinS oder sogar verschachtelten Funktionen mit Zeichenfolgenumkehrungen vorschlage und was nicht, denke ich, dass die Leute die Frage nicht wirklich verstehen. Oder vielleicht verstehe ich es nicht.

Soweit ich weiß, ist C # nicht (zumindest in der Altsteinzeit Version , die ich immer noch bin mit , aus den letzten zehn Jahren) eine Funktion , um sauber produzieren mehrzeiligen String - Literale , die während der Kompilierung aufgelöst werden können , anstatt die Ausführung.

Vielleicht unterstützen aktuelle Versionen dies, aber ich dachte, ich würde den Unterschied teilen, den ich zwischen Strings und String-Literalen wahrnehme.

AKTUALISIEREN:

(Aus dem Kommentar von MeowCat2012) Sie können. Der "+" - Ansatz von OP ist der beste. Laut Spezifikation ist die Optimierung garantiert: http://stackoverflow.com/a/288802/9399618


1
Die Verwirrung, die einige (einschließlich ich) bei der Betrachtung der ursprünglichen Frage hatten, ist, dass das Here-Doc-Format (Shell, PHP, Perl, ...) die Zeilenumbrüche enthält. Wenn das OP also mit dem Heredoc von PHP verglichen wird, sollte das Einbeziehen der Zeilenumbrüche kein Problem gewesen sein.
Tanktalus

Genau. Soweit ich weiß, ist Ihre Antwort "Nein, das können Sie in C # nicht tun" richtig.
TamaMcGlinn

Mir wurde gesagt, dass in Java eine solche verkettete Zeichenfolge zu einem einzelnen Zeichenfolgenliteral im kompilierten Bytecode wird. Vielleicht auch dot Net?
Meow Cat 2012

2
Du kannst. Der "+" - Ansatz von OP ist der beste. Laut Spezifikation ist die Optimierung garantiert: stackoverflow.com/a/288802/9399618 Trotzdem sind Sie einer der wenigen, die die Frage verstehen. Wäre es möglich, potenziell irreführende, aber akzeptierte Antworten zu entfernen oder zu falten?
Meow Cat 2012

1
Danke für den Hinweis, @ MeowCat2012. Wenn man sich dekompilierten Code ansieht, scheint dies tatsächlich der Fall zu sein.
Carvo Loco

12

Ich habe dies nicht gesehen, daher werde ich es hier veröffentlichen (wenn Sie daran interessiert sind, eine Zeichenfolge zu übergeben, können Sie dies auch tun.) Die Idee ist, dass Sie die Zeichenfolge in mehrere Zeilen aufteilen und Ihren eigenen Inhalt hinzufügen können (auch in mehreren Zeilen) in beliebiger Weise. Hier kann "tableName" an die Zeichenfolge übergeben werden.

    private string createTableQuery = "";

    void createTable(string tableName)
    {

         createTableQuery = @"CREATE TABLE IF NOT EXISTS
                ["+ tableName  + @"] (
               [ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
               [Key] NVARCHAR(2048)  NULL, 
               [Value] VARCHAR(2048)  NULL
                                )";
    }

10
ziemlich gefährlich würde ich sagen: leicht für jemanden, auf diese Weise eine SQL-Injektion zu machen.
Kai

4
Solange Sie wissen, dass alle Ihre Variablen (falls vorhanden!) In Ihrer Abfragezeichenfolge aus Codekonstanten oder einer anderen sicheren Quelle stammen, ist dies createTable("MyTable"); in jedem Fall die Frage des OP, wie mehrzeilige Zeichenfolgenliterale direkt in Code eingegeben werden können , nicht wie man Datenbankabfragen per se erstellt. :)
dbeachy1

2
sollte wahrscheinlich einen String Builder verwenden, insbesondere wenn die Anzahl der Pluspunkte (+) viel ist.
Gldraphael

8

Sie können @ und "" verwenden .

        string sourse = @"{
        ""items"":[
        {
            ""itemId"":0,
            ""name"":""item0""
        },
        {
            ""itemId"":1,
            ""name"":""item1""
        }
        ]
    }";

2
Sie sollten erklären, was jeder tut, da @ für wörtliche Zeichenfolge steht und "" für doppelte Anführungszeichen steht.
Nach dem

4

Ja, Sie können eine Zeichenfolge in mehrere Zeilen aufteilen, ohne Zeilenumbrüche in die eigentliche Zeichenfolge einzufügen, aber es ist nicht schön:

string s = $@"This string{
string.Empty} contains no newlines{
string.Empty} even though it is spread onto{
string.Empty} multiple lines.";

Der Trick besteht darin, Code einzuführen, der als leer ausgewertet wird. Dieser Code kann Zeilenumbrüche enthalten, ohne die Ausgabe zu beeinträchtigen. Ich habe diesen Ansatz aus dieser Antwort auf eine ähnliche Frage angepasst .

Es gibt anscheinend einige Verwirrung darüber, was die Frage ist, aber es gibt zwei Hinweise darauf, dass wir hier ein Zeichenfolgenliteral wollen, das keine Zeilenumbruchzeichen enthält, deren Definition mehrere Zeilen umfasst. (In den Kommentaren sagt er es und "hier ist was ich habe" zeigt Code, der keine Zeichenfolge mit Zeilenumbrüchen erstellt.)

Dieser Unit-Test zeigt die Absicht:

    [TestMethod]
    public void StringLiteralDoesNotContainSpaces()
    {
        string query = "hi"
                     + "there";
        Assert.AreEqual("hithere", query);
    }

Ändern Sie die obige Definition der Abfrage so, dass es sich um ein Zeichenfolgenliteral handelt, anstatt um die Verkettung von zwei Zeichenfolgenliteralen, die vom Compiler möglicherweise zu einem optimiert werden.

Der C ++ - Ansatz besteht darin, jede Zeile mit einem Backslash zu beenden, wodurch das Zeilenumbruchzeichen maskiert wird und nicht in der Ausgabe angezeigt wird. Leider gibt es dann immer noch das Problem, dass jede Zeile nach der ersten linksbündig ausgerichtet werden muss, um dem Ergebnis kein zusätzliches Leerzeichen hinzuzufügen.

Es gibt nur eine Option, die nicht auf Compiler-Optimierungen beruht, die möglicherweise nicht stattfinden, nämlich Ihre Definition in eine Zeile zu setzen. Wenn Sie sich auf Compiler-Optimierungen verlassen möchten, ist das +, das Sie bereits haben, großartig. Sie müssen die Zeichenfolge nicht nach links ausrichten, Sie erhalten keine Zeilenumbrüche im Ergebnis und es ist nur eine Operation, keine Funktionsaufrufe, um eine Optimierung zu erwarten.


1
Kreativ. Es scheint jedoch, dass (nicht bestätigt) dies als Formatzeichenfolge behandelt wird und möglicherweise optimiert wird oder nicht. Andererseits ist der "+" - Ansatz von OP der beste. Laut Spezifikation ist die Optimierung garantiert: stackoverflow.com/a/288802/9399618
Meow Cat 2012

4

Fügen Sie mehrere Zeilen hinzu: Verwenden Sie @

string query = @"SELECT foo, bar
FROM table
WHERE id = 42";

Fügen Sie der Mitte Zeichenfolgenwerte hinzu: Verwenden Sie $

string text ="beer";
string query = $"SELECT foo {text} bar ";

Mehrzeilige Zeichenfolge Fügen Sie der Mitte Werte hinzu: Verwenden Sie $ @

string text ="Customer";
string query = $@"SELECT foo, bar
FROM {text}Table
WHERE id = 42";

3

Wenn Sie keine Leerzeichen / Zeilenumbrüche möchten, scheint das Hinzufügen von Zeichenfolgen zu funktionieren:

var myString = String.Format(
  "hello " + 
  "world" +
  " i am {0}" +
  " and I like {1}.",
  animalType,
  animalPreferenceType
);
// hello world i am a pony and I like other ponies.

Sie können das oben genannte hier ausführen , wenn Sie möchten.


2
Ein (versehentlich demonstrierter) Fehler bei diesem Ansatz ist, dass Sie sehr vorsichtig sein müssen, um Leerzeichen einzuschließen, wo Sie sie möchten. Ich würde einen konsistenteren Ansatz empfehlen als ich (z. B. immer am Anfang der Zeile).
Rattray

string + string ist genau das, womit OP begonnen hat.
TamaMcGlinn

1

Ich weiß, dass ich etwas spät zur Party komme, aber ich möchte https://www.buildmystring.com/ zukünftigen Lesern dieses Threads empfehlen . Über diese Site können Sie jeden Code in ein C # -String-Literal konvertieren.


-10

Sie können diese beiden Methoden verwenden:

    private static String ReverseString(String str)
    {
        int word_length = 0;
        String result = "";
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == ' ')
            {
                result = " " + result;
                word_length = 0;
            }
            else
            {
                result = result.Insert(word_length, str[i].ToString());
                word_length++;
            }
        }
        return result;
    }
//NASSIM LOUCHANI
    public static string SplitLineToMultiline(string input, int rowLength)
    {
        StringBuilder result = new StringBuilder();
        StringBuilder line = new StringBuilder();

        Stack<string> stack = new Stack<string>(ReverseString(input).Split(' '));

        while (stack.Count > 0)
        {
            var word = stack.Pop();
            if (word.Length > rowLength)
            {
                string head = word.Substring(0, rowLength);
                string tail = word.Substring(rowLength);

                word = head;
                stack.Push(tail);
            }

            if (line.Length + word.Length > rowLength)
            {
                result.AppendLine(line.ToString());
                line.Clear();
            }

            line.Append(word + " ");
        }

        result.Append(line);
        return result.ToString();
    }

In der SplitLineToMultiline () müssen Sie die Zeichenfolge definieren, die Sie verwenden möchten, und die Zeilenlänge. Dies ist sehr einfach. Vielen Dank .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.