หลายสตริงตัวอักษรใน C #


1046

มีวิธีง่ายๆในการสร้างสตริงหลายบรรทัดตัวอักษรใน C #?

นี่คือสิ่งที่ฉันมีตอนนี้:

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

ฉันรู้ว่า PHP มี

<<<BLOCK

BLOCK;

C # มีบางอย่างที่คล้ายกันหรือไม่


1
ในตัวอย่างของคุณไม่มีตัวแบ่งบรรทัด คุณต้องการมันไหม
weiqure

8
ไม่ได้ฉันต้องการได้หลายบรรทัดเพื่อเหตุผลด้านความสะอาดการมองเห็น / รหัสเท่านั้น
เจตน์

6
ในกรณีนั้นสตริงคำต่อคำมีตัวแบ่งบรรทัด คุณสามารถใช้ @ "... " แทนที่ (Environment.NewLine, "") หากต้องการ
weiqure

9
คุณควรพิจารณาการผูก42เป็นพารามิเตอร์โดยเฉพาะถ้ามันมาจากการป้อนข้อมูลของผู้ใช้เพื่อหลีกเลี่ยงการฉีด SQL
Jens Mühlenhoff

@ JensMühlenhoffจะมีคนฉีดสตริงที่กำหนดรหัสที่กำหนดไว้ในรหัสได้อย่างไร
นายบอย

คำตอบ:


1590

คุณสามารถใช้@สัญลักษณ์ด้านหน้า a stringเพื่อจัดรูปแบบสตริง verbatim ตามตัวอักษร :

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

คุณไม่จำเป็นต้องหลบเลี่ยงอักขระพิเศษเมื่อคุณใช้วิธีการนี้ยกเว้นเครื่องหมายคำพูดคู่ตามที่แสดงในคำตอบของ Jon Skeet


43
มันเป็นตัวอักษรสตริงอยู่แล้ว - มันเป็นสตริงตัวอักษรทุกคำที่มีเครื่องหมาย @
Jon Skeet

95
ถ้าสายของคุณมีราคาสองครั้ง ( ") คุณสามารถหลบหนีพวกเขาต้องการเพื่อ: '' (ครับตัวละครทั้งสองอ้างดับเบิล)
โมดดิบ

8
มีวิธีทำข้างต้นโดยไม่สร้างบรรทัดใหม่หรือไม่ ฉันมีข้อความยาวมากที่ฉันต้องการเห็นใน IDE โดยไม่ต้องใช้เครื่องหมายบวก ("hi" + "there")
noelicus

2
@ noelicus - ไม่จริง แต่คุณสามารถแก้ไขได้โดยใช้เทคนิคของ weiqure ด้านบนของ:@"my string".Replace(Environment.NewLine, "")
John Rasch

8
@afsharm คุณสามารถใช้ $ @ "text"
Patrick McDonald

566

มันเรียกว่าสตริงตัวอักษรทุกตัวใน C # และมันเป็นเพียงเรื่องของการใส่ @ ก่อนตัวอักษร สิ่งนี้ไม่เพียง แต่อนุญาตให้มีหลายบรรทัด แต่มันยังปิดการหลบหนี ตัวอย่างเช่นคุณสามารถทำได้:

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

ซึ่งรวมถึงการขึ้นบรรทัดใหม่ (โดยใช้การแบ่งบรรทัดใดก็ได้ที่แหล่งที่มาของคุณมี) ลงในสตริง สำหรับ SQL นั้นไม่เพียง แต่ไม่เป็นอันตราย แต่อาจปรับปรุงความสามารถในการอ่านได้ทุกที่ที่คุณเห็นสตริง - แต่ในที่อื่น ๆ อาจไม่จำเป็นต้องใช้ซึ่งในกรณีนี้คุณอาจไม่จำเป็นต้องใช้สตริง verbatim แบบหลายบรรทัดตามตัวอักษร หรือลบออกจากสตริงผลลัพธ์

บิตเดียวของการหลบหนีคือถ้าคุณต้องการเครื่องหมายคำพูดคู่คุณต้องเพิ่มสัญลักษณ์เครื่องหมายคำพูดคู่พิเศษ:

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

2
คำตอบนี้ไม่ถูกต้อง มันแนะนำบรรทัดใหม่ที่ OP ไม่ต้องการ
TamaMcGlinn

@TamaMcGlinn: ฉันจะเพิ่มบางอย่างลงในคำตอบเกี่ยวกับสิ่งนั้น - มันไม่ชัดเจนเมื่อ OP เขียนคำถาม
Jon Skeet

105

ปัญหาเกี่ยวกับการใช้สตริงตัวอักษรฉันพบคือมันสามารถทำให้โค้ดของคุณดู " แปลก " เพราะเพื่อที่จะไม่ได้รับช่องว่างในสตริงตัวเองก็จะต้องชิดซ้าย:

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

yuck

ดังนั้นวิธีที่ฉันชอบใช้ซึ่งทำให้ทุกอย่างสอดคล้องกับส่วนที่เหลือของรหัสของคุณ:

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

และแน่นอนถ้าคุณเพียงต้องการที่จะมีเหตุผลแยกบรรทัดของคำสั่ง SQL เหมือนคุณอยู่และไม่จริงต้องบรรทัดใหม่คุณสามารถเสมอเพียงทดแทนสำหรับEnvironment.NewLine" "


2
ขอบคุณมาก นอกจากนี้ String.Concat ทำงานในทำนองเดียวกันและไม่จำเป็นต้องมีตัวคั่น
เซท

ขอบคุณ ฉันชอบ String.Join ที่มีตัวคั่น "" สำหรับ SQL เนื่องจากอนุญาตให้มีการเยื้อง / การจับคู่แบบพาเรนและหลีกเลี่ยงการเพิ่มช่องว่างนำหน้า
Rob ที่ TVSeries.com

7
ในขณะที่น่าเกลียดรุ่นแรกต้องใช้รหัสในการทำงาน ตัวเลือกที่สองเห็นได้ชัดว่ามีค่าใช้จ่ายในการรันเพื่อเชื่อมสตริงที่แยกจากกัน
Gone Coding

@GoneCoding คุณแน่ใจหรือไม่ คอมไพเลอร์อาจปรับการต่อข้อมูลให้เหมาะสม
William Jockusch

@WilliamJockusch: โดยทั่วไปการเรียกใช้ฟังก์ชันที่ไม่ใช่ตัวดำเนินการ (เช่นเข้าร่วม) จะไม่ถูกเปลี่ยนแปลงและไม่ได้รับการปรับให้เหมาะสม ดีที่สุดตรวจสอบรหัสที่คอมไพล์ แต่ฉันจะวางเงินที่โทรไม่เหมาะ
Gone Coding

104

gotcha อื่น ๆ ที่ต้องระวังคือการใช้ตัวอักษรสตริงในสตริงรูปแบบ ในกรณีนี้คุณต้องหลีกเลี่ยงวงเล็บปีกกา / วงเล็บเหลี่ยม '{' และ '}'

// 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
แล้วมันมีความแตกต่างอะไรบ้าง? เมื่อมีหรือไม่มี "@" คุณจะต้องเพิ่ม "{{" เพื่อให้ได้ "{" เป็นอักขระที่พิมพ์ได้มันเป็นเรื่องของ String รูปแบบไม่ใช่เนื้อหาสตริง
greenoldman

12
เป็น gotcha ที่โดดเด่นสำหรับผู้ที่ต้องการใส่รหัส Javascript ในสตริงซึ่งอาจทำได้บ่อยในตัวอักษรสตริงคำต่อคำมากกว่าสตริงปกติ
Ed Brannin

2
ใน C # 6.0 ใหม่คุณสามารถใช้ตัวดำเนินการพร็อพเพอร์ตี้ที่จัดทำดัชนีร่วมกับสตริงตัวอักษรคำต่อคำ (เช่น $ @ "มูลค่านี้ {this.Value}";)
Heliac

2
@Heliac ฉันคิดว่าคุณหมายถึงสตริง interpolated ยังสามารถตามตัวอักษรด้วยไวยากรณ์ที่ var query = $ @ "เลือก foo, บาร์จากตารางที่ id = {id}";
ไบรอันรี่

102

จากหมายเหตุด้านข้างด้วย C # 6.0 ตอนนี้คุณสามารถรวมสตริงที่สอดแทรกเข้ากับสตริงตัวอักษรคำต่อคำ:

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

10
เยี่ยมฉันไม่เคยรู้มาก่อนจนกระทั่งตอนนี้ หากใครสนใจ: $ thingy ถูกเรียกว่า "Interpolated Strings" และคุณสามารถอ่านรายละเอียดได้ที่นี่: msdn.microsoft.com/en-us/library/dn961160.aspx
Hauke ​​P.

tx แก้ไขถ้อยคำ
Heliac

1
ฉันคิดว่าวงเล็บปีกกาตัวอักษรนั้นจะต้องเป็นสองเท่าเช่น$@"{{example literal text { fooString }. }}" นี้อาจทำให้เกิดความสับสนบางอย่างเพราะ Angular, React และ Vue.js ใช้การประชุมที่ตรงกันข้าม
Patrick Szalapski

58

ทำไมคนถึงสับสนกับสตริงตัวอักษร? คำตอบที่ยอมรับได้เป็นคำตอบที่ดีสำหรับคำถามอื่น ไม่ให้คนนี้

ฉันรู้ว่านี่เป็นหัวข้อเก่า แต่ฉันมาที่นี่พร้อมกับคำถามเดียวกันกับ OP และน่าผิดหวังที่ผู้คนเข้าใจผิด หรือบางทีฉันอ่านผิดฉันไม่รู้

สตริงที่พูดโดยประมาณคือขอบเขตของหน่วยความจำคอมพิวเตอร์ที่ในระหว่างการทำงานของโปรแกรมจะมีลำดับไบต์ที่สามารถแมปกับอักขระข้อความได้ สตริงตัวอักษรในทางกลับกันเป็นชิ้นส่วนของรหัสที่มายังไม่ได้รวบรวมที่แสดงถึงค่าที่ใช้ในการเริ่มต้นสตริงในภายหลังในระหว่างการดำเนินการของโปรแกรมที่ปรากฏ

ใน C # คำสั่ง ...

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

... ไม่สร้างสตริงสามบรรทัด แต่เป็นหนึ่งซับ; การต่อกันของสามสาย (แต่ละค่าเริ่มต้นจากตัวอักษรที่แตกต่างกัน) ไม่มีซึ่งประกอบด้วยตัวดัดแปลงบรรทัดใหม่

สิ่งที่ OP ดูเหมือนว่าจะถาม - อย่างน้อยสิ่งที่ฉันจะถามด้วยคำเหล่านั้น - ไม่ใช่วิธีการที่จะแนะนำในการรวบรวมสตริงการแบ่งบรรทัดที่เลียนแบบที่พบในซอร์สโค้ด แต่วิธีการแยกเพื่อความชัดเจนเป็นเวลานาน บรรทัดเดียวของข้อความในซอร์สโค้ดโดยไม่แนะนำตัวแบ่งในสตริงที่คอมไพล์ และโดยไม่ต้องใช้เวลาดำเนินการนาน ๆ การใช้งานร่วมกับสตริงย่อยหลายอันมาจากซอร์สโค้ด เหมือนเครื่องหมายแบ็กสแลชต่อท้ายภายในสตริงหลายบรรทัดใน javascript หรือ C ++

การแนะนำการใช้งานของคำต่อคำสตริง, ไม่เป็นไรStringBuilders, String.Joinหรือฟังก์ชั่นที่ซ้อนกันกับการกลับรายการสตริงและสิ่งที่ไม่ทำให้ฉันคิดว่าคนไม่เข้าใจคำถามจริงๆ หรือบางทีฉันไม่เข้าใจ

เท่าที่ฉันรู้ C # ไม่ (อย่างน้อยในรุ่นยุคที่ฉันยังคงใช้จากทศวรรษก่อนหน้า) มีคุณสมบัติในการผลิตตัวอักษรสตริงหลายบรรทัดที่สามารถแก้ไขได้ในระหว่างการรวบรวมมากกว่าการดำเนินการ

อาจเป็นรุ่นปัจจุบันที่สนับสนุน แต่ฉันคิดว่าฉันจะแบ่งปันความแตกต่างที่ฉันรับรู้ระหว่างสตริงและตัวอักษรสตริง

UPDATE:

(จากความคิดเห็นของ MeowCat2012) คุณสามารถ วิธีการ "+" โดย OP เป็นวิธีที่ดีที่สุด ตามข้อกำหนดการรับประกันการเพิ่มประสิทธิภาพ: http://stackoverflow.com/a/288802/9399618


1
ความสับสนบางอย่าง (รวมถึงตัวฉันเอง) อาจดูคำถามเดิมก็คือรูปแบบ doc ที่นี่ (เชลล์, php, perl, ... ) รวมถึงบรรทัดใหม่ ดังนั้นถ้า OP เปรียบเทียบกับ heredoc ของ PHP ดังนั้นการรวมบรรทัดใหม่จะไม่เป็นปัญหา
Tanktalus

เผง เท่าที่ฉันรู้คำตอบของคุณ "ไม่คุณไม่สามารถทำได้ใน C #" ถูกต้อง
TamaMcGlinn

ฉันบอกว่าใน Java, สตริงที่ต่อกันดังกล่าวจะกลายเป็นสตริงตัวอักษรเดียวใน bytecode ที่รวบรวม บางที dot dot ก็ทำได้เช่นกัน?
Meow Cat 2012

2
คุณสามารถ. วิธีการ "+" โดย OP เป็นวิธีที่ดีที่สุด ตามข้อกำหนดการรับประกันการปรับให้เหมาะสม: stackoverflow.com/a/288802/9399618คุณยังเป็นหนึ่งในไม่กี่คนที่เข้าใจคำถามนี้ เป็นไปได้ไหมที่จะลบหรือพับคำตอบที่อาจทำให้เข้าใจผิด แต่ยอมรับได้?
Meow Cat 2012

1
ขอบคุณสำหรับคำใบ้ @ MeowCat2012 เมื่อมองไปที่โค้ดที่ถอดรหัสแล้วดูเหมือนว่าจะเป็นเช่นนั้น
Carvo Loco

12

ฉันไม่ได้เห็นสิ่งนี้ดังนั้นฉันจะโพสต์ไว้ที่นี่ (ถ้าคุณสนใจที่จะส่งสตริงคุณสามารถทำได้เช่นกัน) แนวคิดก็คือคุณสามารถแยกสตริงออกเป็นหลายบรรทัดและเพิ่มเนื้อหาของคุณเอง (เช่นกัน ในหลายบรรทัด) ในแบบที่คุณต้องการ ที่นี่ "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
                                )";
    }

10
ค่อนข้างอันตรายฉันจะบอกว่า: ง่ายสำหรับใครบางคนในการสร้าง sql-injections อย่างนั้น
Kai

4
มันดีตราบใดที่คุณรู้ว่าตัวแปรทั้งหมดของคุณ (ถ้ามี!) ในสตริงการสืบค้นของคุณมาจากค่าคงที่ของรหัสหรือแหล่งที่ปลอดภัยอื่น ๆ - เช่นcreateTable("MyTable"); ในกรณีใด ๆ คำถามของ OP คือเกี่ยวกับวิธีป้อนตัวอักษรสตริงหลายบรรทัดโดยตรงในรหัส ไม่ใช่วิธีสร้างคิวรีฐานข้อมูลต่อหนึ่งรายการ :)
dbeachy1

2
ควรใช้ตัวสร้างสตริงโดยเฉพาะอย่างยิ่งหากจำนวน pluses (+) มาก
gldraphael

8

คุณสามารถใช้@และ""

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

2
คุณควรอธิบายว่าแต่ละอันทำหน้าที่อะไรอย่างไรเช่นเดียวกับ @ สำหรับสตริงคำต่อคำและ "" มีไว้เพื่อหลีกเลี่ยงการใส่เครื่องหมายคำพูดคู่
หยุด

4

ใช่คุณสามารถแบ่งสตริงออกเป็นหลายบรรทัดโดยไม่ต้องแนะนำบรรทัดใหม่เป็นสตริงจริง แต่มันก็ไม่สวยเลย:

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 ++ จะเป็นการสิ้นสุดแต่ละบรรทัดด้วยแบ็กสแลชทำให้อักขระขึ้นบรรทัดใหม่ถูกหลีกเลี่ยงและไม่ปรากฏในเอาต์พุต น่าเสียดายที่ยังมีปัญหาที่แต่ละบรรทัดหลังจากบรรทัดแรกต้องอยู่ในแนวเดียวกันเพื่อไม่เพิ่มช่องว่างเพิ่มเติมให้กับผลลัพธ์

มีเพียงตัวเลือกเดียวเท่านั้นที่ไม่พึ่งพาการปรับให้เหมาะสมของคอมไพเลอร์ที่อาจไม่เกิดขึ้นซึ่งก็คือการใส่คำจำกัดความของคุณในหนึ่งบรรทัด หากคุณต้องการพึ่งพาการปรับให้เหมาะสมของคอมไพเลอร์ตัว + ที่คุณมีอยู่นั้นยอดเยี่ยม คุณไม่จำเป็นต้องจัดเรียงสตริงซ้ายคุณไม่ได้รับการขึ้นบรรทัดใหม่ในผลลัพธ์และเป็นเพียงการดำเนินการเดียวไม่มีการเรียกใช้ฟังก์ชันเพื่อคาดหวังการปรับให้เหมาะสม


1
ความคิดสร้างสรรค์ อย่างไรก็ตามดูเหมือนว่า (ไม่ยืนยัน) สิ่งนี้จะถือว่าเป็นสตริงรูปแบบและอาจหรือไม่อาจปรับให้เหมาะสม ในทางกลับกันวิธี "+" โดย OP นั้นดีที่สุด รับประกันการเพิ่มประสิทธิภาพตามสเป็ค: stackoverflow.com/a/288802/9399618
Meow Cat 2012

4

เพิ่มหลายบรรทัด: use @

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";

3

หากคุณไม่ต้องการเว้นวรรค / บรรทัดใหม่การเพิ่มสตริงดูเหมือนจะใช้งานได้:

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.

คุณสามารถเรียกใช้ข้างต้นที่นี่หากคุณต้องการ


2
ข้อบกพร่องหนึ่งข้อ (แสดงโดยไม่ได้ตั้งใจ) ด้วยวิธีนี้คือคุณจะต้องระมัดระวังเป็นพิเศษในการรวมช่องว่างที่คุณต้องการ ฉันขอแนะนำวิธีการที่สอดคล้องมากกว่าที่ฉันทำ (เช่นเสมอที่จุดเริ่มต้นของบรรทัด)
rattray

string + string เป็นสิ่งที่ OP เริ่มต้นด้วย
TamaMcGlinn

1

ฉันรู้ว่าฉันมาช้าไปงานปาร์ตี้ แต่ฉันอยากจะแนะนำhttps://www.buildmystring.com/สำหรับผู้อ่านในอนาคตของกระทู้นี้ คุณสามารถแปลงรหัสใด ๆ ให้เป็นสตริงตัวอักษร C # ได้โดยใช้เว็บไซต์นี้


-10

คุณสามารถใช้สองวิธีนี้:

    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 () คุณจะต้องกำหนดสตริงที่คุณต้องการใช้และความยาวแถวมันง่ายมาก ขอบคุณ .

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.