C # 'da çok satırlı dize hazır bilgisi


1046

C # bir çok satırlı dize hazır bilgi oluşturmak için kolay bir yolu var mı?

İşte şimdi ne var:

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

PHP var biliyorum

<<<BLOCK

BLOCK;

C # benzer bir şey var mı?


1
Örneğinizde satır sonu yok. Onları istiyor musun?
weiqure

8
Hayır. Görünürlük / kod temizliği nedeniyle yalnızca birden fazla satır istedim.
Chet

6
Bu durumda, sözcük dizeleri satır sonlarını içerir. @ "..." kullanabilirsiniz. İsterseniz (Environment.NewLine, "") değiştirin.
weiqure

9
42SQL enjeksiyonundan kaçınmak için, özellikle kullanıcı girişinden geliyorsa, parametre olarak bağlamayı düşünmelisiniz .
Jens Mühlenhoff

@ JensMühlenhoff Birisi kodda tanımlanan sabit kodlu bir dizeyi nasıl enjekte eder?
Bay Boy

Yanıtlar:


1590

Kelimenin tam anlamıyla bir dize değişmezi oluşturmak için a'nın@ önündeki simgeyi kullanabilirsiniz :string

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

Jon Skeet'in cevabında gösterilen çift tırnak işaretleri dışında, bu yöntemi kullandığınızda özel karakterlerden kaçmanız da gerekmez .


43
Zaten bir dize değişmezidir . @ İşaretiyle kelimesi kelimesine bir dize değişmezidir.
Jon Skeet

95
dizeniz çift tırnak (") içeriyorsa, onlardan şu şekilde kaçabilirsiniz:" "(bu iki çift tırnaklı karakterdir)
Muad'Dib

8
Yukarıdakileri yeni çizgiler oluşturmadan yapmanın bir yolu var mı? Artı kullanmak zorunda kalmadan IDE içine sarılmış görmek istiyorum gerçekten uzun bir metin parçası var ("merhaba" + "orada").
noelicus

2
@noelicus - gerçekten değil, ancak aşağıdaki yöntemlerin üstündeki weiqure tekniğini kullanarak geçici çözüm bulabilirsiniz:@"my string".Replace(Environment.NewLine, "")
John Rasch

8
@afsharm $ @ "text" kullanabilirsiniz
Patrick McDonald

566

Buna C # ' da kelimesi kelimesine bir dize değişmezi denir ve bu yalnızca @ değerini değişmezden önce koyma meselesidir. Bu sadece birden fazla satıra izin vermekle kalmaz, aynı zamanda kaçmayı da kapatır. Örneğin, şunları yapabilirsiniz:

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

Bununla birlikte, dizeye satır sonlarını (kaynağınızdaki satır sonunu kullanarak) içerir. SQL için, bu sadece zararsız değil, aynı zamanda dizeyi gördüğünüz her yerde okunabilirliği de artırır - ancak başka yerlerde gerekli olmayabilir, bu durumda başlamak için çok satırlı bir sözcük dizgisi değişmezini kullanmanız gerekmez, veya ortaya çıkan dizeden kaldırın.

Kaçan tek şey, bir çift tırnak istiyorsanız, ekstra bir çift tırnak sembolü eklemeniz gerektiğidir:

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

2
Bu cevap yanlış; OP'nin arzu etmediği yeni satırlar getiriyor.
TamaMcGlinn

@TamaMcGlinn: Bunun cevabına bir şey ekleyeceğim - OP'nin soruyu ne zaman yazdığı belli değildi.
Jon Skeet

105

Dize değişmez kullanarak kullanarak sorun ben dize kendisi boşluk almak için, tamamen hizalanmış bırakılması gerekir çünkü kod biraz " garip " görünmesini sağlayabilirsiniz :

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

Yuck.

Bu yüzden her şeyi kodunuzun geri kalanıyla güzel hizalanmış tutan, kullanmayı sevdiğim çözüm:

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

Sadece senin gibi mantıklı bir SQL deyiminin satırları bölmek isteyen ve aslında yeni bir satır gerekmiyorsa Ve tabii ki, her zaman sadece yerini alabilir Environment.NewLineiçin " ".


2
Çok daha temiz, teşekkürler. Ayrıca, String.Concat benzer şekilde çalışır ve ayırıcı gerektirmez.
Seth

Teşekkürler. Ben "Girinti / paren eşleme için izin verir ve önde gelen boşluk eklemek zorunda kaçındığı için" "için ayırıcı ile String.Join SQL gibi.
Rob TVSeries.com'da

7
Çirkin olsa da, ilk sürüm çalıştırmak için kod gerektirmez . İkinci seçeneğin, ayrı dizeleri birleştirmek için bir çalışma zamanı yükü olduğu açıktır.
Gitti Kodlama

@GoneCoding, bundan emin misin? Derleyici bitiştirmeyi optimize edebilir.
William Jockusch

@WilliamJockusch: genellikle operatör olmayan fonksiyon çağrıları (birleştirme gibi) sağlam kalır ve optimize edilmez. En iyi derlenmiş kodu kontrol ama arama optimize edilmemiş para yatıyordu.
Gitti Kodlama

104

İzlenmesi gereken bir diğer şey de string.Format'da string değişmezlerinin kullanılmasıdır. Bu durumda, '{' ve '}' kıvırcık parantezlerinden / parantezlerinden kaçmanız gerekir.

// 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
Ve ne fark eder? "@" Olsun ya da olmasın, "{" 'yi yazdırılabilir karakter olarak almak için iki katına çıkmalısınız, bu string içeriği değil String.Format meselesidir.
greenoldman

12
Javascript kodunu bir dizeye koymak isteyen insanlar için dikkate değer bir şeydir, bu da normal dizelerden daha çok kelime dizgisinde yapılabilir.
Ed Brannin

2
Yeni C # 6.0'da, bir dizine alınmış özellik operatörünü kelimesi kelimesine dizgi değişmeziyle birlikte kullanabilirsiniz (örneğin, bu $ @ "Değer {this.Value}";)
Heliac

2
@Heliac Bence enterpolasyonlu dizgilerin bu sözdizimi ile değişmez olabileceğini düşünüyorum. var query = $ @ "foo seçin, tablodan bar = id = {id}";
brianary

102

Bir yan not olarak, C # 6.0 ile enterpolasyonlu dizeleri gerçek dize değişmeziyle birleştirebilirsiniz:

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

10
Güzel, şimdiye kadar bunu bilmiyordum. Herkes ilgileniyorsa: $ thingy "Interpolated Strings" olarak adlandırılır ve burada ayrıntılı olarak okuyabilirsiniz: msdn.microsoft.com/en-us/library/dn961160.aspx
Hauke ​​P.

tx, ifadeler düzeltildi
Heliac

1
Değişmez bir küme ayracı, o zaman iki katına çıkarılması gerektiğini varsayıyorum, örneğin $@"{{example literal text { fooString }. }}" Angular, React ve Vue.js karşı konvansiyonu kullandığı için bu biraz karışık olabilir.
Patrick Szalapski

58

İnsanlar neden dizeleri dizgi değişmezleriyle karıştırmaya devam ediyor? Kabul edilen cevap, farklı bir soruya harika bir cevaptır; buna değil.

Bunun eski bir konu olduğunu biliyorum, ama buraya muhtemelen OP ile aynı soru ile geldim ve insanların nasıl yanlış okuduğunu görmek sinir bozucu. Ya da belki de onu yanlış okuyorum, bilmiyorum.

Kabaca bir dize, bir programın yürütülmesi sırasında, metin karakterleriyle eşleştirilebilen bir bayt dizisi içeren bilgisayar belleğinin bir bölgesidir. Bir dizgi değişmezi, diğer taraftan, henüz derlenmemiş olan ve daha sonra içinde göründüğü programın yürütülmesi sırasında bir dizeyi başlatmak için kullanılan değeri temsil eden bir kaynak kod parçasıdır.

C # 'da ifade ...

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

... gelmez üç satır dize ancak bir tek astar üretmek; hiçbiri yeni satır değiştirici içermeyen üç dizenin (her biri farklı bir değişmez değerden başlatılan) birleştirilmesi.

OP'nin -en azından bu kelimelerle sorduğum şey- sorduğu şey, derlenmiş dizede, kaynak kodunda bulunanları taklit eden satır sonlarının nasıl tanıtılacağı değil, uzun süre netlik için nasıl ayrılacağıdır. kaynak kodu metnin, tek satır olmadan derlenmiş dizede sonları tanıtan. Ve uzun bir yürütme süresi gerektirmeden, kaynak kodundan gelen birden fazla alt dizeye katılmak için harcadı. Javascript veya C ++ 'da çok satırlı bir dize değişmezi içindeki sondaki ters eğik çizgiler gibi.

Kelimelerin iplerini tersine çevirerek ve neyi içermeyen kelimesi kelimesine dizelerin, nevermind StringBuilders, String.Joins ve hatta iç içe işlevlerin kullanılmasını önermek , insanların soruyu gerçekten anlamadıklarını düşündürüyor. Ya da belki de anlamıyorum.

Bildiğim kadarıyla, C # (en azından hala kullandığım paleolitik versiyonda, önceki on yıldan beri) derleme sırasında yürütme yerine çözülebilen çok satırlı dize değişmezlerini üretme özelliğine sahip değil.

Belki şu anki sürümler bunu destekliyor, ancak dizeler ve dize değişmezleri arasında algıladığım farkı paylaşacağımı düşündüm.

GÜNCELLEME:

(MeowCat2012'nin yorumundan) Yapabilirsiniz. OP'nin "+" yaklaşımı en iyisidir. Spesifikasyonlara göre optimizasyon garanti edilir: http://stackoverflow.com/a/288802/9399618


1
Bazılarının (ben de dahil) orijinal soruya baktığı kafa karışıklığı, burada-doc formatının (kabuk, php, perl, ...) yeni satırları içermesidir. Bu yüzden OP, PHP'nin yorumlu metinleriyle karşılaştırılıyorsa, yeni satırları eklemek bir sorun olmamalı.
Tanktalus

Kesinlikle. Bildiğim kadarıyla cevabınız "hayır, bunu C # ile yapamazsınız" doğrudur.
TamaMcGlinn

Java'da böyle bir birleştirilmiş dizenin derlenmiş bayt kodunda tek bir dizgi değişmezi olacağı söylendi. Belki nokta Net de öyle?
Miyav Kedi 2012

2
Yapabilirsin. OP'nin "+" yaklaşımı en iyisidir. Spesifikasyonlara göre optimizasyon garanti edilir: stackoverflow.com/a/288802/9399618 Yine de soruyu anlayan birkaç kişiden birisiniz. Potansiyel olarak yanıltıcı ancak kabul edilen cevapları kaldırmak veya katlamak mümkün müdür?
Miyav Kedi 2012

1
İpucu için teşekkürler, @ MeowCat2012. Bazı decompiled koda baktığımızda, aslında böyle görünüyor.
Carvo Loco

12

Bunu görmedim, bu yüzden buraya göndereceğim (eğer bir dize geçmek istiyorsanız, bunu da yapabilirsiniz.) Fikir, dizeyi birden fazla satırda kesip kendi içeriğinizi ( birden çok satırda) istediğiniz şekilde. Burada "tableName" dizeye aktarılabilir.

    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
oldukça tehlikeli diyebilirim: Birisinin bu şekilde sql enjeksiyon yapması kolay.
Kai

4
Sorgu dizenizdeki tüm değişkenlerinizin (varsa!) Kod sabitlerinden veya başka bir güvenli kaynaktan geldiğini bildiğiniz sürece sorun yoktur - ör createTable("MyTable"); . Her durumda, OP'nin sorusu, çok satırlı dize değişmez değerlerinin doğrudan koda nasıl girileceği ile ilgilidir. , kendi başına veritabanı sorguları oluşturmak nasıl değil. :)
dbeachy1

2
özellikle artı (+) sayısı çok ise, bir dize oluşturucu kullanmalıdır.
gldraphael

8

@ Ve "" kullanabilirsiniz .

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

2
Her biri için ne işe yaradığını açıklamalısınız.
AFract

4

Evet, bir dizeyi, gerçek dizeye yeni satırlar eklemeden birden çok satıra bölebilirsiniz, ancak güzel değildir:

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

Hile, boş olarak değerlendirilen kodu tanıtmaktır ve bu kod, çıktıyı etkilemeden yeni satırlar içerebilir. Bu yaklaşımı bu cevaptan benzer bir soruya uyarladım .

Görünüşe göre sorunun ne olduğu konusunda bir karışıklık var, ancak burada istediğimiz şeyin, tanımı birden çok satıra yayılan yeni satır karakterleri içermeyen bir dize değişmezi olduğuna dair iki ipucu var. (yorumlarda öyle diyor ve "işte burada ne var", içinde yeni satırlar olan bir dize oluşturmayan kodu gösterir)

Bu birim testi amacı gösterir:

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

Yukarıdaki sorgu tanımını, derleyici tarafından tek bir duruma getirilip optimize edilemeyen iki dize değişmezinin birleştirilmesi yerine, bir dize değişmezi olacak şekilde değiştirin.

C ++ yaklaşımı, her satırı bir ters eğik çizgi ile sonlandırmak ve yeni satır karakterinin kaçmasına ve çıktıda görünmemesine neden olacaktır. Maalesef, sonuca ilave boşluk eklemek için ilk satırdan sonraki her satırın hizalı olarak bırakılması sorunu hala devam etmektedir.

Gerçekleşmeyebilecek derleyici optimizasyonlarına güvenmeyen tek bir seçenek vardır, bu da tanımınızı bir satıra koymaktır. Derleyici optimizasyonlarına güvenmek istiyorsanız, sahip olduğunuz + harika; dizeyi sola hizalamak zorunda değilsiniz, sonuçta yeni satırlar elde edemezsiniz ve optimizasyonun beklenmesi için yalnızca bir işlemdir, işlev çağrısı yoktur.


1
Yaratıcı. Bununla birlikte, (onaylanmadı) bunun biçim dizesi olarak değerlendirileceği ve optimize edilebileceği veya optimize edilmeyebileceği görülmektedir. Öte yandan OP'nin "+" yaklaşımı en iyisidir. Spesifikasyonlara göre optimizasyon garanti edilir: stackoverflow.com/a/288802/9399618
Meow Cat 2012

4

Birden çok satır ekleyin: use @

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

Ortaya Dize Değerleri ekleyin: use $

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

Birden çok satır dizesi Ortaya Değer Ekle: $ @ kullanın

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

3

Boşluk / yeni satır istemiyorsanız, dize eklemenin işe yaradığı görülmektedir:

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.

İsterseniz yukarıdakileri burada çalıştırabilirsiniz .


2
Bu yaklaşımla ilgili bir (yanlışlıkla gösterilen) kusur, onları istediğiniz yere dahil etmek için çok dikkatli olmanız gerektiğidir. Aldığımdan daha tutarlı bir yaklaşım öneriyorum (örneğin; her zaman satırın başında).
çıngırak

string + string OP ile başlamıştı.
TamaMcGlinn

1

Partiye biraz geç kaldığımı biliyorum ama bu konunun gelecekteki okuyucuları için https://www.buildmystring.com/ tavsiye etmek istiyorum . Bu siteyi kullanarak herhangi bir kodu C # string değişmezine dönüştürebilirsiniz.


-10

Bu iki yöntemi kullanabilirsiniz:

    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 () içinde, kullanmak istediğiniz dizeyi ve satır uzunluğunu tanımlamanız gerekir, çok basittir. Teşekkür ederim .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.