web-dev-qa-db-fra.com

Littéral de chaîne multiligne en C #

Existe-t-il un moyen simple de créer un littéral de chaîne multiligne en C #?

Voici ce que j'ai maintenant:

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

Je sais que PHP a

<<<BLOCK

BLOCK;

Est-ce que C # a quelque chose de similaire?

918
Chet

Vous pouvez utiliser le symbole @ devant un string pour former un littéral de chaîne mot à mot :

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

Vous avez également vous n'êtes pas obligé d'échapper aux caractères spéciaux lorsque vous utilisez cette méthode, à l'exception des guillemets doubles, comme indiqué dans la réponse de Jon Skeet.

1412
John Rasch

C'est ce qu'on appelle chaîne littérale exacte en C #, et il suffit de mettre @ avant le littéral. Non seulement cela autorise plusieurs lignes, mais cela désactive également l'échappement. Ainsi, par exemple, vous pouvez faire:

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

Le seul inconvénient est que si vous voulez une citation double, vous devez ajouter un symbole de citation double supplémentaire:

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

Un autre aspect à surveiller est l'utilisation de littéraux de chaîne dans string.Format. Dans ce cas, vous devez échapper des accolades/crochets '{' et '}'.

// 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)
100
Martin Clarke

Le problème avec l'utilisation du littéral de chaîne que je trouve est qu'il peut donner à votre code un aspect "bizarre" car, pour ne pas laisser d'espaces dans la chaîne elle-même, il doit être complètement aligné à gauche:

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

Beurk.

Donc, la solution que j'aime utiliser, qui maintient tout bien aligné avec le reste de votre code est la suivante:

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

Et bien sûr, si vous souhaitez simplement diviser logiquement les lignes d'une instruction SQL comme si vous étiez et n'avez pas besoin d'une nouvelle ligne, vous pouvez toujours remplacer Environment.NewLine par " ".

94
dav_i

En remarque, avec C # 6.0, vous pouvez maintenant combiner des chaînes interpolées avec le littéral de chaîne textuel:

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

Pourquoi les gens continuent-ils à confondre les chaînes avec les littéraux de chaîne? La réponse acceptée est une excellente réponse à une question différente. pas à celui-ci.

Je sais que c'est un sujet ancien, mais je suis venu ici avec peut-être la même question que celle du PO, et il est frustrant de voir comment les gens continuent à mal le lire. Ou peut-être que je me trompe, je ne sais pas.

En gros, une chaîne de caractères est une région de la mémoire de l'ordinateur qui, lors de l'exécution d'un programme, contient une séquence d'octets pouvant être mappés à des caractères de texte. Un littéral de chaîne, en revanche, est un morceau de code source, non encore compilé, qui représente la valeur utilisée pour initialiser une chaîne ultérieurement, lors de l'exécution du programme dans lequel elle apparaît.

En C #, la déclaration ...

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

... ne produit pas une chaîne de trois lignes mais une ligne; la concaténation de trois chaînes (chacune initialisée à partir d'un littéral différent) dont aucune ne contient de modificateur de nouvelle ligne.

Ce que le PO semble demander - du moins ce que je demanderais avec ces mots - n’est pas de savoir comment introduire, dans la chaîne compilée, les sauts de ligne qui imitent ceux trouvés dans le code source, mais comment casser pour plus de clarté , une seule ligne de texte dans le code source sans introduisant des ruptures dans la chaîne compilée. Et sans nécessiter de temps d’exécution prolongé, nous avons passé la tâche de joindre les multiples sous-chaînes provenant du code source. Comme les barres obliques inverses au sein d'un littéral de chaîne multiligne en javascript ou en C++.

Suggérer l’utilisation de chaînes textuelles, ne importe quoi StringBuilders, String.Joins ou même de fonctions imbriquées avec inversions de chaînes et autres éléments, me fait penser que les gens ne comprennent pas vraiment la question. Ou peut-être je ne le comprends pas.

Pour autant que je sache, C # n'a pas (du moins dans la version paléolithique que j'utilise encore, de la décennie précédente) une fonctionnalité permettant de produire proprement des chaînes littérales multilignes qui peut être résolu pendant la compilation plutôt que l'exécution.

Peut-être que les versions actuelles le supportent, mais je pensais partager la différence que je perçois entre les chaînes et les littéraux de chaîne.

MISE À JOUR:

(Du commentaire de MeowCat2012) Vous pouvez. Le "+" de OP est le meilleur. Selon les spécifications, l'optimisation est garantie: http://stackoverflow.com/a/288802/9399618

43
Carvo Loco

Je ne l'ai pas vu, je vais donc le poster ici (si vous êtes intéressé par une chaîne, vous pouvez également le faire.) L'idée est que vous pouvez séparer la chaîne sur plusieurs lignes et ajouter votre propre contenu (également sur plusieurs lignes) comme vous le souhaitez. Ici, "tableName" peut être passé dans la chaîne.

    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
RobertHana

Vous pouvez utiliser @ et "".

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

Oui, vous pouvez diviser une chaîne en plusieurs lignes sans introduire de nouvelles lignes dans la chaîne, mais ce n’est pas joli:

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

L'astuce consiste à introduire un code dont la valeur est vide, et ce code peut contenir des nouvelles lignes sans affecter la sortie. J'ai adapté cette approche de cette réponse à une question similaire.

Il y a apparemment une certaine confusion quant à la nature de la question, mais il y a deux allusions: nous voulons ici un littéral de chaîne ne contenant aucun caractère de nouvelle ligne, dont la définition s'étend sur plusieurs lignes. (dans les commentaires qu'il dit, et "voici ce que j'ai" montre un code qui ne crée pas de chaîne avec des retours à la ligne)

Ce test unitaire montre l'intention:

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

Modifiez la définition ci-dessus de la requête afin qu'il s'agisse d'un littéral de chaîne, au lieu de la concaténation de deux littéraux de chaîne qui peuvent être optimisés ou non par le compilateur.

L’approche C++ consiste à terminer chaque ligne par une barre oblique inverse, ce qui provoque l’échappement du caractère de nouvelle ligne et ne l’affiche pas dans la sortie. Malheureusement, il subsiste toujours le problème suivant: chaque ligne après la première doit être laissée alignée afin de ne pas ajouter d'espaces supplémentaires au résultat.

Il n'y a qu'une seule option qui ne repose pas sur des optimisations du compilateur qui pourraient ne pas se produire, à savoir mettre votre définition sur une seule ligne. Si vous souhaitez vous appuyer sur les optimisations du compilateur, le + que vous avez déjà est excellent; vous n'êtes pas obligé d'aligner à gauche la chaîne, vous n'obtenez pas de nouvelles lignes dans le résultat, et ce n'est qu'une opération, sans appel de fonction, pour laquelle l'optimisation est attendue.

3
TamaMcGlinn

Si vous ne voulez pas d'espaces/de nouvelles lignes, l'ajout de chaînes semble fonctionner:

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.

Vous pouvez exécuter ce qui précède ici si vous le souhaitez.

1
rattray