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

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

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

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

Я знаю, что в PHP есть

<<<BLOCK

BLOCK;

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


person Chet    schedule 08.07.2009    source источник
comment
В вашем примере нет разрывов строк. Ты хочешь их?   -  person weiqure    schedule 09.07.2009
comment
Нет. Мне нужно несколько строк только из соображений наглядности / чистоты кода.   -  person Chet    schedule 09.07.2009
comment
В этом случае дословные строки содержат разрывы строк. Вы можете использовать @ .... Заменить (Environment.NewLine,), если хотите.   -  person weiqure    schedule 09.07.2009
comment
Вам следует рассмотреть возможность привязки 42 в качестве параметра, особенно если он поступает от пользователя, чтобы избежать SQL-инъекции.   -  person Jens Mühlenhoff    schedule 24.10.2013
comment
@weiqure: Environment.NewLine не обязательно отражает разрывы строк в строке, поскольку разрывы строк берутся так, как они встречаются в исходном коде. Таким образом, можно писать код даже с разными разрывами строк в каждой строке, которые все отличаются от того, что Environment.NewLine сообщает в целевой системе!   -  person mmmmmmmm    schedule 06.01.2021


Ответы (11)


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

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

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

person John Rasch    schedule 08.07.2009
comment
В любом случае это строковый литерал - это строковый литерал дословно со знаком @. - person Jon Skeet; 09.07.2009
comment
если ваша строка содержит двойные кавычки (), вы можете избежать их следующим образом: (это два символа двойных кавычек) - person Muad'Dib; 09.07.2009
comment
Есть ли способ сделать это без создания новых строк? У меня есть очень длинный фрагмент текста, который я хотел бы видеть в среде IDE без использования плюса (привет +). - person noelicus; 12.12.2012
comment
@noelicus - не совсем, но вы можете обойти это, используя описанную выше технику weiqure: @"my string".Replace(Environment.NewLine, "") - person John Rasch; 12.12.2012
comment
MonoDevelop-Unity здесь задыхается на%. - person Jonny; 02.03.2015
comment
@ фактически заставляет C # обрабатывать строковые литералы так же, как VB обрабатывает строковые литералы. - person Achilles; 02.04.2015
comment
Как насчет комбинации @ и нового оператора C # $? - person Afshar Mohebi; 03.11.2015
comment
@afsharm Вы можете использовать $ @ text - person Patrick McDonald; 29.04.2016
comment
Вот пример строки XML, обратите внимание на двойные числа: @ ‹soapenv: Envelope xmlns: soapenv = schemas.xmlsoap.org/soap/envelope xmlns: ord = tempuri.org/OrderEntry.Xsd› ‹soapenv: Заголовок› ‹/ soapenv: Заголовок› - person Kevin .NET; 17.08.2017
comment
Это неверный ответ. Ваша строка запроса содержит символы новой строки, а это не то, о чем просили. Я считаю, что правильный ответ - нет, вы не можете сделать это на C #. См. Ответ Карко Локо. Допускаю, что немного неясно, что он имел в виду, говоря о многострочном строковом литерале, но его вот то, что у меня есть, должно развеять любые сомнения относительно его намерений. - person TamaMcGlinn; 21.12.2018
comment
В C ++ вы должны заканчивать каждую строку обратной косой чертой, чтобы получить строковый литерал без новых строк, определение которого охватывает несколько строк. Я считаю, что именно это и просил OP. - person TamaMcGlinn; 21.12.2018

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

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

Однако это включает в себя разрывы строк (используя любой разрыв строки, который есть в вашем источнике) в строку. Для SQL это не только безвредно, но и, вероятно, улучшает читаемость везде, где вы видите строку, но в других местах это может не требоваться, и в этом случае вам либо нужно не использовать многострочную дословный строковый литерал, чтобы начать с него, или удалите его из результирующей строки.

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

string quote = @"Jon said, ""This will work,"" - and it did!";
person Jon Skeet    schedule 08.07.2009
comment
Это неверный ответ; он вводит новые строки, которые OP не желает. - person TamaMcGlinn; 23.10.2019
comment
@TamaMcGlinn: Я добавлю кое-что в ответ по этому поводу - было непонятно, когда ОП написал вопрос. - person Jon Skeet; 23.10.2019

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

string camlCondition = $@"
<Where>
    <Contains>
        <FieldRef Name='Resource'/>
        <Value Type='Text'>{(string)parameter}</Value>
    </Contains>
</Where>";
person Riegardt Steyn    schedule 13.08.2015
comment
Круто, я до сих пор не знал об этом. Если кому-то интересно: $ thingy называется Interpolated Strings, и вы можете прочитать об этом подробно здесь: msdn.microsoft.com/en-us/library/dn961160.aspx - person Hauke P.; 20.02.2016
comment
tx, исправил формулировку - person Riegardt Steyn; 20.02.2016
comment
Я предполагаю, что буквальная фигурная скобка должна быть удвоена, например ,$@"{{example literal text { fooString }. }}" Это может запутать некоторых, потому что Angular, React и Vue.js используют противоположное соглашение. - person Patrick Szalapski; 21.05.2018
comment
Это классная находка. Хотя, если ваши интерполированные строковые значения вызывают методы, например: {date.ToString("yyyy-mm-dd")}, вы можете рассмотреть ответ @dav_i, поскольку интерполяция более чистая, без необходимости возиться с двойными кавычками - person AndrewGentry; 09.09.2020

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

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

Фу.

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

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

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

person dav_i    schedule 07.08.2014
comment
Намного чище, спасибо. Кроме того, String.Concat работает аналогично и не требует разделителя. - person Seth; 13.01.2015
comment
Уродливая первая версия не требует запуска кода. Второй вариант, очевидно, требует дополнительных затрат времени выполнения для объединения отдельных строк. - person Gone Coding; 03.03.2016
comment
Спасибо за это, но тут ничего не поделаешь в случае дословной записи атрибутов. Например: [Всплывающая подсказка (@ Очень длинная строка .....)], в которой вы не могли запускать какие-либо коды. Я планировал использовать дословно, потому что код выглядит некрасиво как аргумент из одной строки, когда я работаю с полноэкранным редактором. Но затем дословно добавляет к самой строке другие невидимые символы, так что я не смог найти другого пути. - person 5argon; 24.05.2017
comment
Хотя он будет компилироваться нормально и выглядит лучше, он не может пройти проверку кода, потому что он уязвим для атаки с использованием SQL-инъекции. Вам не разрешено создавать какие-либо строки запроса во время выполнения. Он должен быть постоянным. - person John Henckel; 03.10.2018
comment
Мне тоже нравится этот метод, потому что он делает интерполяцию чище. Представьте, что вы хотите сделать что-то вроде "The", "Quick", $"{fox.color}", "Fox" - person AndrewGentry; 09.09.2020

Еще одна проблема, на которую следует обратить внимание, - это использование строковых литералов в 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)
person Martin Clarke    schedule 24.09.2009
comment
И какая разница? С или без @ вы должны удвоить {{, чтобы получить {как печатный символ, это зависит от String.Format, а не от содержимого строки. - person greenoldman; 27.08.2011
comment
Это заметная проблема для людей, которые хотят поместить код Javascript в строку, что может быть сделано чаще в буквальных строковых литералах, чем в обычных строках. - person Ed Brannin; 15.03.2013
comment
В новом C # 6.0 вы можете использовать оператор индексированного свойства вместе с дословным строковым литералом (например, это $ @ Value равно {this.Value};) - person Riegardt Steyn; 13.08.2015
comment
@Heliac Я думаю, вы имеете в виду, что интерполированные строки также могут быть буквальными с этим синтаксисом. var query = $ @ select foo, панель из таблицы, где id = {id}; - person brianary; 01.11.2017

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

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

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

В C # инструкция ...

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

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

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

Предложение использовать дословные строки, не говоря уже о StringBuilders, String.Joins или даже вложенных функциях с переворотами строк и т.д., заставляет меня думать, что люди действительно не понимают вопрос. А может я этого не понимаю.

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

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

ОБНОВИТЬ:

(Из комментария MeowCat2012) Вы можете. Подход «+» OP является лучшим. Согласно спецификации оптимизация гарантирована: http://stackoverflow.com/a/288802/9399618

person Carvo Loco    schedule 17.07.2016
comment
Путаница, которую некоторые (включая меня), возможно, испытывали при рассмотрении исходного вопроса, заключается в том, что формат here-doc (shell, php, perl, ...) включает символы новой строки. Итак, если OP сравнивается с heredoc PHP, то включение новых строк не должно было быть проблемой. - person Tanktalus; 12.03.2018
comment
Точно. Насколько мне известно, ваш ответ «нет», вы не можете сделать это на C #, правильный. - person TamaMcGlinn; 21.12.2018
comment
Мне сказали, что в Java такая объединенная строка станет единственным строковым литералом в скомпилированном байт-коде. Может быть, dot Net тоже так поступает? - person Meow Cat 2012; 23.07.2019
comment
Вы можете. + Подход OP - лучший. Согласно спецификации, оптимизация гарантирована: stackoverflow.com/a/288802/9399618 Тем не менее, вы один из немногих, кто понимает вопрос. Можно ли удалить или свернуть потенциально вводящие в заблуждение, но принятые ответы? - person Meow Cat 2012; 23.07.2019
comment
Спасибо за подсказку, @ MeowCat2012. Глядя на декомпилированный код, кажется, что это действительно так. - person Carvo Loco; 24.07.2019

Добавьте несколько строк: используйте @

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

Добавьте строковые значения в середину: используйте $

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

Многострочная строка Добавьте значения в середину: используйте $ @

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

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

        string sourse = @"{
        ""items"":[
        {
            ""itemId"":0,
            ""name"":""item0""
        },
        {
            ""itemId"":1,
            ""name"":""item1""
        }
        ]
    }";
person vovkas    schedule 06.06.2018
comment
Вы должны объяснить, что делает каждый, поскольку @ означает дословную строку и позволяет избежать двойных кавычек. - person AFract; 22.08.2018
comment
Есть ли быстрый способ сделать это без поиска / замены всех двойных кавычек, например, во вставленном JSON? - person ryanwebjackson; 14.07.2020

Я этого не видел, поэтому опубликую здесь (если вы заинтересованы в передаче строки, вы тоже можете это сделать). Идея состоит в том, что вы можете разбить строку на несколько строк и добавить свой собственный контент (также на нескольких строках) любым способом. Здесь "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
                                )";
    }
person RobertHana    schedule 19.09.2014
comment
довольно опасно, я бы сказал: кому-то так легко сделать sql-инъекции. - person Kai; 10.11.2014
comment
Это нормально, если вы знаете, что все ваши переменные (если они есть!) В строке запроса происходят из констант кода или другого безопасного источника - например, createTable("MyTable");. В любом случае вопрос OP заключался в том, как вводить многострочные строковые литералы непосредственно в код, а не как создавать запросы к базе данных как таковые. :) - person dbeachy1; 28.02.2015
comment
вероятно, следует использовать конструктор строк, особенно если количество плюсов (+) много. - person galdin; 09.07.2015

Да, вы можете разбить строку на несколько строк, не вводя символы новой строки в фактическую строку, но это не очень красиво:

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

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

Очевидно, существует некоторая путаница в том, в чем заключается вопрос, но есть два намека на то, что здесь нам нужен строковый литерал, не содержащий никаких символов новой строки, определение которого охватывает несколько строк. (в комментариях он так говорит, а «вот что у меня» показывает код, который не создает строку с новой строкой в ​​ней)

Этот модульный тест показывает намерение:

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

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

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

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

person TamaMcGlinn    schedule 21.12.2018
comment
Творческий. Однако кажется, что (не подтверждено) это будет рассматриваться как строка формата и может или не может быть оптимизировано. С другой стороны, подход OP является лучшим. Согласно спецификации оптимизация гарантирована: stackoverflow.com/a/288802/9399618 - person Meow Cat 2012; 23.07.2019

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

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.

При желании вы можете выполнить указанное выше здесь.

person rattray    schedule 13.05.2015
comment
Один (непреднамеренно продемонстрированный) недостаток этого подхода заключается в том, что вы должны быть очень осторожны, добавляя пробелы там, где вы хотите. Я бы порекомендовал более последовательный подход, чем я использовал (например, всегда в начале строки). - person rattray; 13.05.2015
comment
Строка + строка - это как раз то, с чего начал ОП. - person TamaMcGlinn; 21.12.2018