Chuỗi nhiều chữ trong C #


1046

Có cách nào dễ dàng để tạo một chuỗi nhiều chữ trong C # không?

Đây là những gì tôi có bây giờ:

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

Tôi biết PHP có

<<<BLOCK

BLOCK;

C # có gì tương tự không?


1
Không có ngắt dòng trong ví dụ của bạn. Bạn có muốn chúng?
weiqure

8
Không. Tôi chỉ muốn nhiều dòng vì lý do sạch sẽ về mã / hiển thị.
Chet

6
Trong trường hợp đó, các chuỗi nguyên văn chứa các ngắt dòng. Bạn có thể sử dụng @ "...". Thay thế (Môi trường.NewLine, "") nếu bạn muốn.
weiqure

9
Bạn nên xem xét ràng buộc 42như là một tham số, đặc biệt nếu nó xuất phát từ đầu vào của người dùng, để tránh việc tiêm SQL.
Jens Mühlenhoff

@ JensMühlenhoff ai đó sẽ tiêm một chuỗi mã hóa cứng, được xác định trong mã?
Cậu bé

Câu trả lời:


1590

Bạn có thể sử dụng @biểu tượng ở phía trước a stringđể tạo thành một chuỗi nguyên văn :

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

Bạn cũng không phải thoát các ký tự đặc biệt khi bạn sử dụng phương pháp này, ngoại trừ dấu ngoặc kép như trong câu trả lời của Jon Skeet.


43
Dù sao đó cũng là một chuỗi ký tự - đó là một chuỗi nguyên văn với ký hiệu @.
Jon Skeet

95
nếu chuỗi của bạn chứa dấu ngoặc kép ("), bạn có thể thoát chúng như vậy:" "(đó là hai ký tự trích dẫn kép)
Muad'Dib

8
Có cách nào để làm ở trên mà không cần tạo ra các dòng mới? Tôi có một đoạn văn bản thực sự dài mà tôi muốn thấy được gói trong IDE mà không phải sử dụng dấu cộng ("hi" + "there").
noelicus

2
@noelicus - không thực sự, nhưng bạn có thể giải quyết điều đó bằng cách sử dụng kỹ thuật của weiqure ở trên:@"my string".Replace(Environment.NewLine, "")
John Rasch

8
@afsharm Bạn có thể sử dụng $ @ "văn bản"
Patrick McDonald

566

Nó được gọi là một chuỗi nguyên văn theo nghĩa đen trong C #, và đó chỉ là vấn đề đặt @ trước nghĩa đen. Điều này không chỉ cho phép nhiều dòng, mà còn tắt thoát. Vì vậy, ví dụ bạn có thể làm:

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

Tuy nhiên, điều này bao gồm các ngắt dòng (sử dụng bất kỳ dòng nào ngắt nguồn của bạn có) thành chuỗi. Đối với SQL, điều đó không chỉ vô hại mà còn có thể cải thiện khả năng đọc ở bất cứ nơi nào bạn thấy chuỗi - nhưng ở những nơi khác có thể không bắt buộc, trong trường hợp đó, bạn không cần phải sử dụng chuỗi ký tự nguyên văn nhiều dòng để bắt đầu, hoặc loại bỏ chúng khỏi chuỗi kết quả.

Điều duy nhất để thoát là nếu bạn muốn có một trích dẫn kép, bạn phải thêm một biểu tượng trích dẫn kép:

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

2
Câu trả lời này không chính xác; nó giới thiệu những dòng mới mà OP không mong muốn.
TamaMcGlinn

@TamaMcGlinn: Tôi sẽ thêm điều gì đó vào câu trả lời về điều đó - không rõ ràng khi OP viết câu hỏi.
Jon Skeet

105

Vấn đề với việc sử dụng chuỗi ký tự tôi thấy là nó có thể làm cho mã của bạn trông hơi " lạ " vì để không có khoảng trắng trong chính chuỗi, nó phải được căn chỉnh hoàn toàn:

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

Kinh quá.

Vì vậy, giải pháp tôi muốn sử dụng, giúp mọi thứ được liên kết độc đáo với phần còn lại của mã của bạn là:

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

Và tất nhiên, nếu bạn chỉ muốn một cách logic chia tay dòng của một câu lệnh SQL như bạn đang có và không thực sự cần một dòng mới, bạn có thể luôn luôn chỉ cần thay thế Environment.NewLinecho " ".


2
Sạch sẽ hơn nhiều, cảm ơn. Ngoài ra, String.Concat hoạt động tương tự và không yêu cầu dấu phân cách.
Seth

Cảm ơn. Tôi thích String.Join với dấu phân cách "" cho SQL vì nó cho phép thụt lề / khớp paren và tránh phải thêm khoảng trắng hàng đầu.
Cướp tại TVSeries.com

7
Mặc dù xấu, phiên bản đầu tiên không yêu cầu chạy mã . Tùy chọn thứ hai rõ ràng có một chi phí thời gian chạy để nối các chuỗi riêng biệt.
Mã hóa ngày

@GoneCoding, bạn có chắc về điều đó không? Trình biên dịch có thể tối ưu hóa việc ghép nối đi.
William Jockusch

@WilliamJockusch: nói chung các cuộc gọi chức năng không phải của nhà điều hành (như tham gia) vẫn còn nguyên và không được tối ưu hóa. Tốt nhất kiểm tra mã được biên dịch nhưng tôi sẽ đặt tiền mà cuộc gọi không được tối ưu hóa.
Mã hóa

104

Một gotcha khác để xem là việc sử dụng chuỗi ký tự trong chuỗi.Format. Trong trường hợp đó, bạn cần thoát dấu ngoặc nhọn / ngoặc '{' và '}'.

// 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
Và nó có gì khác biệt? Có hoặc không có "@", bạn phải nhân đôi "{{" để lấy "{" làm ký tự có thể in được, đó là vấn đề của String.Format, không phải nội dung chuỗi.
greenoldman

12
Đó là một hình ảnh xác thực đáng chú ý cho những người muốn đặt mã Javascript vào một chuỗi, việc này có thể được thực hiện thường xuyên hơn bằng các chuỗi ký tự nguyên văn so với các chuỗi thông thường.
Ed Brannin

2
Trong C # 6.0 mới, bạn có thể sử dụng toán tử thuộc tính được lập chỉ mục cùng với chuỗi ký tự nguyên văn (như $ @ "Giá trị này là {this.Value}";)
Heliac

2
@Heliac Tôi nghĩ bạn có nghĩa là các chuỗi nội suy cũng có thể được bằng chữ với cú pháp đó. var query = $ @ "chọn foo, thanh từ bảng trong đó id = {id}";
brianary

102

Là một lưu ý phụ, với C # 6.0, giờ đây bạn có thể kết hợp các chuỗi nội suy với chuỗi nguyên văn theo nghĩa đen:

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

10
Thật tuyệt, tôi không biết về điều này cho đến bây giờ. Nếu bất cứ ai quan tâm: $ thingy được gọi là "Chuỗi nội suy" và bạn có thể đọc chi tiết về nó tại đây: msdn.microsoft.com/en-us/l Library / dc961160.aspx
Hauke ​​P.

tx, đã sửa từ ngữ
Heliac

1
Tôi giả sử một dấu ngoặc nhọn theo nghĩa đen sau đó phải được nhân đôi, ví dụ: $@"{{example literal text { fooString }. }}" Điều này có thể gây nhầm lẫn cho một số người vì Angular, React và Vue.js sử dụng quy ước ngược lại.
Patrick Szalapski

58

Tại sao mọi người cứ nhầm chuỗi với chuỗi ký tự? Câu trả lời được chấp nhận là một câu trả lời tuyệt vời cho một câu hỏi khác nhau; không phải cái này

Tôi biết đây là một chủ đề cũ, nhưng tôi đã đến đây với câu hỏi tương tự như OP, và thật bực bội khi thấy mọi người tiếp tục đọc sai nó như thế nào. Hoặc có lẽ tôi đang đọc sai nó, tôi không biết.

Nói một cách đơn giản, một chuỗi là một vùng bộ nhớ máy tính, trong quá trình thực thi chương trình, chứa một chuỗi các byte có thể được ánh xạ tới các ký tự văn bản. Mặt khác, một chuỗi ký tự là một đoạn mã nguồn, chưa được biên dịch, đại diện cho giá trị được sử dụng để khởi tạo một chuỗi sau này, trong quá trình thực hiện chương trình mà nó xuất hiện.

Trong C #, tuyên bố ...

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

... không tạo ra một chuỗi ba dòng mà là một lớp lót; nối ba chuỗi (mỗi chuỗi được khởi tạo từ một nghĩa đen khác nhau) không có chuỗi nào chứa bộ sửa đổi dòng mới.

Những gì OP dường như đang hỏi - ít nhất là những gì tôi sẽ hỏi với những từ đó - không phải là cách giới thiệu, trong chuỗi được biên dịch, ngắt dòng bắt chước những gì được tìm thấy trong mã nguồn, mà là cách chia nhỏ cho rõ ràng lâu , một dòng văn bản trong mã nguồn mà không giới thiệu các ngắt trong chuỗi đã biên dịch. Và không yêu cầu thời gian thực hiện kéo dài, đã dành tham gia nhiều chuỗi con đến từ mã nguồn. Giống như dấu gạch chéo ngược trong một chuỗi nhiều chữ trong javascript hoặc C ++.

Đề xuất sử dụng các chuỗi nguyên văn, các hàm không bao giờ StringBuilder, String.Joins hoặc thậm chí lồng nhau với đảo ngược chuỗi và điều gì không, khiến tôi nghĩ rằng mọi người không thực sự hiểu câu hỏi. Hoặc có thể tôi không hiểu nó.

Theo như tôi biết, C # không (ít nhất là trong phiên bản màu nhạt mà tôi vẫn đang sử dụng, từ thập kỷ trước) có một tính năng để sản xuất sạch các chuỗi ký tự đa dòng có thể được giải quyết trong quá trình biên dịch thay vì thực thi.

Có thể các phiên bản hiện tại hỗ trợ nó, nhưng tôi nghĩ tôi muốn chia sẻ sự khác biệt mà tôi cảm nhận được giữa các chuỗi và chuỗi ký tự.

CẬP NHẬT:

(Từ bình luận của MeowCat2012) Bạn có thể. Cách tiếp cận "+" của OP là tốt nhất. Theo thông số kỹ thuật, việc tối ưu hóa được đảm bảo: http://stackoverflow.com/a/288802/9399618


1
Một sự nhầm lẫn mà một số người (bao gồm cả bản thân tôi) có thể đã nhìn vào câu hỏi ban đầu là định dạng tài liệu ở đây (shell, php, perl, ...) bao gồm các dòng mới. Vì vậy, nếu OP đang so sánh với di truyền của PHP, thì bao gồm cả các dòng mới không phải là một vấn đề.
Tanktalus

Chính xác. Theo tôi biết, câu trả lời của bạn "không, bạn không thể làm điều này trong C #" là chính xác.
TamaMcGlinn

Tôi đã nói rằng trong Java, một chuỗi được nối như vậy sẽ trở thành một chuỗi ký tự duy nhất trong mã byte được biên dịch. Có lẽ dot Net cũng làm như vậy?
Mèo Meow 2012

2
Bạn có thể. Cách tiếp cận "+" của OP là tốt nhất. Theo thông số kỹ thuật, việc tối ưu hóa được đảm bảo: stackoverflow.com/a/288802/9399618 Vẫn là một trong số ít người hiểu câu hỏi. Có thể loại bỏ hoặc gấp các câu trả lời có khả năng gây hiểu lầm nhưng được chấp nhận?
Mèo Meow 2012

1
Cảm ơn gợi ý, @ MeowCat2012. Nhìn vào một số mã dịch ngược, có vẻ như đó thực sự là trường hợp.
Carvo Loco

12

Tôi chưa thấy điều này, vì vậy tôi sẽ đăng nó ở đây (nếu bạn quan tâm đến việc truyền chuỗi, bạn cũng có thể làm điều này.) Ý tưởng là bạn có thể ngắt chuỗi trên nhiều dòng và thêm nội dung của riêng bạn (cũng trên nhiều dòng) theo bất kỳ cách nào bạn muốn. Ở đây "tên bảng" có thể được truyền vào chuỗi.

    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
khá nguy hiểm Tôi muốn nói: dễ dàng cho ai đó thực hiện tiêm sql theo cách đó.
Kai

4
Sẽ tốt thôi nếu bạn biết rằng tất cả các biến của bạn (nếu có!) Trong chuỗi truy vấn của bạn đến từ các hằng mã hoặc một nguồn an toàn khác - ví dụ: createTable("MyTable"); Trong mọi trường hợp, câu hỏi của OP là về cách nhập trực tiếp chuỗi ký tự chuỗi đa dòng trong mã , không phải làm thế nào để xây dựng các truy vấn cơ sở dữ liệu mỗi se. :)
dbeachy1

2
có lẽ nên sử dụng trình tạo chuỗi, đặc biệt nếu số lượng dấu cộng (+) là rất nhiều.
gldraphael

8

Bạn có thể sử dụng @"" .

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

2
Bạn nên giải thích từng cái, vì @ là cho chuỗi nguyên văn và "" là để thoát dấu ngoặc kép.
Thu hút

4

Có, bạn có thể chia một chuỗi ra thành nhiều dòng mà không cần đưa dòng mới vào chuỗi thực tế, nhưng nó không phải là khá:

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

Mẹo nhỏ là giới thiệu mã đánh giá trống và mã đó có thể chứa dòng mới mà không ảnh hưởng đến đầu ra. Tôi đã điều chỉnh cách tiếp cận này từ câu trả lời này cho một câu hỏi tương tự.

Rõ ràng có một số nhầm lẫn về câu hỏi là gì, nhưng có hai gợi ý rằng điều chúng ta muốn ở đây là một chuỗi ký tự không chứa bất kỳ ký tự dòng mới nào, có định nghĩa kéo dài nhiều dòng. (trong các bình luận anh ấy nói như vậy và "đây là những gì tôi có" hiển thị mã không tạo ra một chuỗi có dòng mới trong đó)

Bài kiểm tra đơn vị này cho thấy ý định:

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

Thay đổi định nghĩa truy vấn ở trên sao cho nó là một chuỗi ký tự, thay vì nối hai chuỗi ký tự chuỗi có thể hoặc không thể được tối ưu hóa thành một chuỗi bởi trình biên dịch.

Cách tiếp cận C ++ sẽ kết thúc mỗi dòng bằng dấu gạch chéo ngược, làm cho ký tự dòng mới được thoát và không xuất hiện trong đầu ra. Thật không may, vẫn còn vấn đề là mỗi dòng sau dòng đầu tiên phải được căn trái để không thêm khoảng trắng vào kết quả.

Chỉ có một tùy chọn không dựa vào tối ưu hóa trình biên dịch có thể không xảy ra, đó là đặt định nghĩa của bạn trên một dòng. Nếu bạn muốn dựa vào tối ưu hóa trình biên dịch, + bạn đã có là tuyệt vời; bạn không phải căn chỉnh chuỗi trái, kết quả là bạn không nhận được dòng mới và đó chỉ là một thao tác, không có chức năng gọi, để mong đợi tối ưu hóa.


1
Sáng tạo. Tuy nhiên, dường như (không được xác nhận) điều này sẽ được coi là chuỗi định dạng và có thể hoặc không thể được tối ưu hóa. Mặt khác, cách tiếp cận "+" của OP là tốt nhất. Theo thông số kỹ thuật, việc tối ưu hóa được đảm bảo: stackoverflow.com/a/288802/9399618
Meow Cat 2012

4

Thêm nhiều dòng: sử dụng @

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

Thêm giá trị chuỗi vào giữa: sử dụng $

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

Nhiều chuỗi dòng Thêm giá trị vào giữa: sử dụng $ @

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

3

Nếu bạn không muốn dấu cách / dòng mới, chuỗi bổ sung dường như hoạt động:

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.

Bạn có thể chạy trên đây nếu bạn muốn.


2
Một lỗ hổng (vô tình được chứng minh) với phương pháp này là bạn phải rất cẩn thận để bao gồm các không gian nơi bạn muốn chúng. Tôi muốn giới thiệu một cách tiếp cận nhất quán hơn tôi đã thực hiện (ví dụ: luôn luôn ở đầu dòng).
rattray

chuỗi + chuỗi chỉ là những gì OP bắt đầu với, mặc dù.
TamaMcGlinn

1

Tôi biết tôi đến bữa tiệc muộn một chút nhưng tôi muốn giới thiệu https://www.buildmystring.com/ cho những độc giả tương lai của chủ đề này. Bạn có thể chuyển đổi bất kỳ mã nào thành chuỗi ký tự C # bằng cách sử dụng trang web này.


-10

Bạn có thể sử dụng hai phương pháp này:

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

Trong SplitLineToMultiline (), bạn cần xác định chuỗi bạn muốn sử dụng và độ dài hàng, rất đơn giản. Cảm ơn bạn .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.