Многострочный строковый литерал в C #

749

Есть ли простой способ создания многострочного литерала строки в С#?

Вот что у меня сейчас:

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

Я знаю, что PHP имеет

<<<BLOCK

BLOCK;

Есть ли у С# что-то подобное?

  • 1
    В вашем примере нет разрывов строк. Ты хочешь их?
  • 5
    Нет. Я хотел только несколько строк для наглядности / чистоты кода.
Показать ещё 2 комментария
Теги:
string

11 ответов

1307
Лучший ответ

Вы можете использовать символ @ перед string, чтобы сформировать дословный строковый литерал:

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

Вы также не должны избегать специальных символов при использовании этого метода, за исключением двойных кавычек, как показано в ответе Джона Скита.

  • 35
    В любом случае это строковый литерал - это дословный строковый литерал со знаком @.
  • 73
    если ваша строка содержит двойные кавычки ("), вы можете избежать их следующим образом:" "(это два символа двойной кавычки)
Показать ещё 16 комментариев
456

В С# он называется дословным строковым литералом, и нужно просто поставить @перед литералом. Это не только позволяет использовать несколько строк, но и отключает экранирование. Так, например, вы можете сделать:

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

Единственное, что можно избежать - это то, что если вам нужна двойная кавычка, вам нужно добавить дополнительный символ двойной кавычки:

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

Еще один вопрос, на который нужно следить, это использование строковых литералов в string.Format. В этом случае вам нужно избежать фигурных скобок/скобок '{' и '}'.

// 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)
  • 13
    И какая разница? С или без "@" вы должны удвоить "{{", чтобы получить "{" в качестве печатаемого символа, это вопрос String.Format, а не строкового содержимого.
  • 12
    Это замечательное замечание для людей, которые хотят поместить код Javascript в строку, что может быть сделано чаще в дословных строковых литералах, чем в обычных строках.
Показать ещё 2 комментария
82

Проблема с использованием строкового литерала, который я нахожу, заключается в том, что он может сделать ваш код немного "странным", потому что для того, чтобы не получить пробелы в самой строке, он должен быть полностью выровнен по левому краю:

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

Тьфу.

Итак, решение, которое мне нравится использовать, которое держит все в хорошем соответствии с остальной частью вашего кода:

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

И, конечно, если вы просто хотите логически разделить строки оператора SQL, как и вы, и на самом деле не нуждаетесь в новой строке, вы всегда можете просто заменить Environment.NewLine на " ".

  • 2
    Гораздо чище, спасибо. Кроме того, String.Concat работает аналогично и не требует разделителя.
  • 0
    Благодарю. Мне нравится String.Join с разделителем "" для SQL, поскольку он допускает отступы / совпадения парен и не требует добавления начального пробела.
Показать ещё 5 комментариев
70

Как примечание, с С# 6.0 теперь вы можете комбинировать интерполированные строки со строковым литералом:

string camlCondition = $@"
<Where>
    <Contains>
        <FieldRef Name='Resource'/>
        <Value Type='Text'>{(string)parameter}</Value>
    </Contains>
</Where>";
  • 10
    Круто, я не знал об этом до сих пор. Если кому-то интересно: $ thingy называется «Интерполированные строки», и вы можете прочитать об этом подробно здесь: msdn.microsoft.com/en-us/library/dn961160.aspx
  • 0
    тх, исправил формулировку
Показать ещё 1 комментарий
31

Почему люди путают строки со строковыми литералами? Принятый ответ - отличный ответ на другой вопрос; не к этому.

Я знаю, что это старая тема, но я пришел сюда, возможно, с тем же вопросом, что и OP, и мне не нравится видеть, как люди не понимают его. Или, может быть, я неправильно понимаю это, я не знаю.

Грубо говоря, строка представляет собой область памяти компьютера, которая во время выполнения программы содержит последовательность байтов, которая может быть отображена на текстовые символы. С другой стороны, строковый литерал представляет собой фрагмент исходного кода, еще не скомпилированный, который представляет значение, используемое для инициализации строки позже, во время выполнения программы, в которой он появляется.

В С# утверждение...

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

... не создает трехстрочную строку, кроме одной строки; конкатенация трех строк (каждая из которых инициализируется из другого литерала), ни один из которых не содержит модификатора новой строки.

То, что OP, кажется, просит - по крайней мере, то, что я хотел бы задать с этими словами, - это не то, как вводить в скомпилированной строке разрывы строк, которые имитируют найденные в исходном коде, но как разбить на четкость длинной, единственной строки текста в исходном коде без введения перерывов в скомпилированной строке. И не требуя расширенного времени выполнения, потраченного на объединение нескольких подстрок, исходящих из исходного кода. Подобно завершающим обратным косым чертам в многострочном строковом литерале в javascript или С++.

Предлагая использование стенографических строк, nevermind StringBuilder s, String.Join или даже вложенных функций с отменой строк, а что нет, заставляет меня думать, что люди не понимают этот вопрос. Или, может быть, я этого не понимаю.

Насколько я знаю, С# не имеет (по крайней мере, в палеолитической версии, которую я все еще использую, с предыдущего десятилетия) есть функция, позволяющая чисто производить строковые строки литералы, которые могут быть разрешены во время компиляция, а не выполнение.

Возможно, текущие версии поддерживают его, но я решил поделиться разницей между строками и строковыми литералами.

  • 1
    Путаница, которую некоторые (включая меня), возможно, имели при взгляде на первоначальный вопрос, заключается в том, что формат here-doc (shell, php, perl, ...) включает переводы строки. Так что если OP сравнивает с heredoc PHP, то включение новых строк не должно было быть проблемой.
  • 0
    Именно так. Насколько я знаю, ваш ответ "нет, вы не можете сделать это в C #" является правильным.
10

Я не видел этого, поэтому я разместил его здесь (если вы заинтересованы в передаче строки, вы тоже можете это сделать.) Идея состоит в том, что вы можете разбить строку на несколько строк и добавить свои собственные (также на нескольких строках) любым способом. Здесь "tableName" может быть передано в строку.

    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
                                )";
    }
  • 8
    Я бы сказал, довольно опасно: кому-то легко делать sql-инъекции.
  • 4
    Это нормально, если вы знаете, что все ваши переменные (если они есть!) В строке запроса происходят из констант кода или другого безопасного источника - например, createTable("MyTable"); В любом случае, вопрос ОП был о том, как вводить многострочные строковые литералы непосредственно в коде, а не о том, как создавать запросы к базе данных как таковые. :)
Показать ещё 1 комментарий
1

Если вам не нужны пробелы/новые строки, похоже, что сложение строк работает:

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.

Вы можете запустить выше здесь, если хотите.

  • 1
    Один (непреднамеренно продемонстрированный) недостаток этого подхода заключается в том, что вы должны быть очень осторожны, чтобы включать места, где вы хотите их. Я бы рекомендовал более последовательный подход, чем я выбрал (например, всегда в начале строки).
  • 0
    Строка + строка - только то, с чего OP начал.
0

Нет, это невозможно в С#. Очевидно, существует некоторая путаница относительно вопроса, но есть два намека на то, что нам нужен строковый литерал, не содержащий символов новой строки, определение которого состоит из нескольких строк. (в комментариях он так говорит, и "здесь то, что у меня есть" показывает код, который не создает строку с символами новой строки в ней)

Этот unit тест показывает намерение:

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

Измените приведенное выше определение запроса, чтобы оно представляло собой один строковый литерал вместо объединения двух строковых литералов, которые могут быть оптимизированы или не оптимизированы компилятором в один.

Подход C++ заключался бы в том, чтобы завершать каждую строку обратной косой чертой, в результате чего символ новой строки экранировался и не появлялся в выходных данных. К сожалению, все еще существует проблема, заключающаяся в том, что каждая строка после первой должна быть выровнена, чтобы не добавлять дополнительные пробелы к результату.

Есть только одна опция, которая не полагается на оптимизацию компилятора, которая может не произойти, - это поместить ваше определение в одну строку. Если вы хотите положиться на оптимизацию компилятора, +, который у вас уже есть, великолепен; вам не нужно выравнивать строку по левому краю, вы не получаете новых строк в результате, и это всего лишь одна операция, без вызовов функций, чтобы ожидать оптимизации.

0

Вы можете использовать @ и "".

        string sourse = @"{
        ""items"":[
        {
            ""itemId"":0,
            ""name"":""item0""
        },
        {
            ""itemId"":1,
            ""name"":""item1""
        }
        ]
    }";
  • 0
    Вы должны объяснить, что делает каждый, так как @ для дословной строки, а "" для экранирования двойных кавычек.
-7

Вы можете использовать эти два метода:

    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();
    }

В SplitLineToMultiline() вам нужно определить строку, которую вы хотите использовать, и длину строки, это очень просто. Спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню