C #의 여러 줄 문자열 리터럴


1046

C #에서 여러 줄 문자열 리터럴을 만드는 쉬운 방법이 있습니까?

여기 내가 지금 가진 것입니다 :

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

나는 PHP가 알고

<<<BLOCK

BLOCK;

C #에는 비슷한 것이 있습니까?


1
예제에는 줄 바꿈이 없습니다. 당신은 그들을 원하십니까?
weiqure

8
아니요. 가시성 / 코드 청결을 위해 여러 줄만 원했습니다.
Chet

6
이 경우 완전 문자열에는 줄 바꿈이 포함됩니다. 원하는 경우 @ "...". Replace (Environment.NewLine, "")를 사용할 수 있습니다.
weiqure

9
42SQL 주입을 피하기 위해 특히 사용자 입력에서 오는 경우 매개 변수로 매개 변수 바인딩을 고려해야합니다 .
Jens Mühlenhoff

@ JensMühlenhoff 누군가 코드로 정의 된 하드 코드 된 문자열을 어떻게 주입합니까?
Mr. Boy

답변:


1589

@a 앞에 있는 기호를 사용하여 완전 문자열 리터럴string 을 형성 할 수 있습니다 .

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

또한 특수 문자를 이스케이프 할 필요가 없습니다 , 당신은이 방법을 사용하면 존 소총의 대답과 같이 큰 따옴표를 제외하고.


43
어쨌든 문자열 리터럴입니다. @ 기호 가있는 완전 문자열 리터럴입니다.
Jon Skeet

95
문자열에 큰 따옴표 ( ")가 포함되어 있으면 다음과 같이 이스케이프 할 수 있습니다." "(두 개의 큰 따옴표 문자)
Muad'Dib

8
새 줄을 만들지 않고 위의 작업을 수행하는 방법이 있습니까? 더하기 ( "hi"+ "there")를 사용하지 않고 IDE에 래핑 된 텍스트가 너무 깁니다.
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의 경우 무해 할뿐만 아니라 문자열을 볼 수있는 곳 어디에서나 가독성을 향상시킬 수 있습니다. 그러나 다른 곳에서는 필요하지 않을 수도 있습니다. 또는 결과 문자열에서 제거하십시오.

이스케이프의 유일한 비트는 큰 따옴표를 원한다면 여분의 큰 따옴표를 추가해야한다는 것입니다.

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

2
이 답변은 잘못되었습니다. OP가 원하지 않는 개행을 소개합니다.
TamaMcGlinn

@TamaMcGlinn : 그에 대한 답변에 뭔가를 추가 할 것입니다. OP가 질문을했을 때 명확하지 않았습니다.
Jon Skeet

105

내가 찾은 문자열 리터럴을 사용할 때의 문제점 은 문자열 자체에서 공백을 얻지 않기 위해 코드를 약간 " 이상하게 " 보일 수 있다는 것입니다 .

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

왝.

따라서 내가 사용하고 싶은 솔루션은 나머지 코드와 잘 어울립니다.

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

당신은 당신이처럼 논리적으로 SQL 문의 라인을 분할 할 실제로 새로운 라인을 필요하지 않은 경우 그리고 물론, 당신은 언제나 대체 할 수 있습니다 Environment.NewLine에 대한 " ".


2
훨씬 더 깨끗합니다. 감사합니다. 또한 String.Concat도 비슷하게 작동하며 구분 기호가 필요하지 않습니다.
세스

감사. 들여 쓰기 / paren-matching을 허용하고 선행 공백을 추가하지 않아도되므로 SQL의 경우 구분 기호 ""를 사용하여 String.Join을 좋아합니다.
TVSeries.com의 Rob

7
추악하지만 첫 번째 버전 은 실행할 코드가 필요하지 않습니다 . 두 번째 옵션에는 분명히 별도의 문자열을 연결하기위한 런타임 오버 헤드가 있습니다.
사라 코딩

@GoneCoding, 확실합니까? 컴파일러는 연결을 최적화 할 수 있습니다.
윌리엄 Jockusch

@WilliamJockusch : 일반적으로 비 연산자 함수 호출 (예 : 조인)은 그대로 유지되며 최적화되지 않습니다. 컴파일 된 코드를 확인하는 것이 좋지만 호출이 최적화되지 않은 돈을 버는 것입니다.
사라 코딩

104

주목해야 할 또 다른 방법은 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)

14
그리고 어떤 차이가 있습니까? "@"의 유무에 관계없이 "{"를 인쇄 가능한 문자로 가져 오려면 "{{"을 두 배로 늘려야합니다. 이는 문자열 내용이 아니라 String.Format의 문제입니다.
greenoldman

12
Javascript 코드를 문자열에 넣기를 원하는 사람들에게는 주목할 만합니다. 일반 문자열보다 문자열 문자열 리터럴에서 더 자주 수행 될 수 있습니다.
Ed Brannin

2
새로운 C # 6.0에서는 색인화 된 속성 연산자를 그대로 문자열 리터럴과 함께 사용할 수 있습니다 (예 : $ @ "Value is {this.Value}";)
Heliac

2
@Heliac 보간 된 문자열이 해당 구문으로 리터럴 될 수 있다고 생각합니다. var query = $ @ "테이블에서 foo를 선택하십시오. 여기서 id = {id}";
brianary

102

부수적으로 C # 6.0에서는 보간 된 문자열을 그대로 문자열 리터럴과 결합 할 수 있습니다.

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

10
쿨, 나는 지금까지 이것에 대해 몰랐다. 누군가 관심이 있다면 : $ 물건은 "보간 된 문자열 (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 ++의 여러 줄 문자열 리터럴 내의 후행 백 슬래시와 같습니다.

그대로 사용하는 문자열, nevermind StringBuilder, String.Joins 또는 심지어 문자열 반전 기능이있는 중첩 함수 사용을 제안하면 사람들이 실제로 질문을 이해하지 못한다고 생각합니다. 아니면 내가 이해하지 못할 수도 있습니다.

내가 아는 한, C # (최소 10 년 전 여전히 사용중인 구석기 시대 버전에서는)은 실행이 아닌 컴파일 중에 해결할 수있는 여러 줄 문자열 리터럴 을 깨끗하게 생성하는 기능이 없습니다.

현재 버전이 지원할 수도 있지만 문자열과 문자열 리터럴 사이의 차이를 공유한다고 생각했습니다.

최신 정보:

(MeowCat2012의 의견에서) 가능합니다. OP의 "+"접근 방식이 가장 좋습니다. 사양에 따르면 최적화가 보장됩니다 : http://stackoverflow.com/a/288802/9399618


1
일부 (나 자신을 포함하여) 원래의 질문을 보았을지도 모르는 혼란은 here-doc 형식 (shell, php, perl 등 ...)에 줄 바꿈이 포함되어 있다는 것입니다. 따라서 OP가 PHP의 heredoc과 비교한다면 개행을 포함하는 것이 문제가되지 않아야합니다.
Tanktalus

바로 그거죠. 내가 아는 한 "아니오, C #에서는 이것을 할 수 없습니다"라는 대답은 맞습니다.
TamaMcGlinn

Java에서 이러한 연결된 문자열은 컴파일 된 바이트 코드에서 단일 문자열 리터럴이 될 것이라고 들었습니다. 닷넷도 그렇게합니까?
Meow Cat 2012 년

2
할 수 있습니다. OP의 "+"접근 방식이 가장 좋습니다. 보장 최적화를 투기하는 것입니다 따르면 stackoverflow.com/a/288802/9399618 여전히 당신에게 몇 가지 이해 질문있는 거 하나. 오해의 소지가 있지만 허용 된 답변을 제거하거나 접을 수 있습니까?
야옹 고양이 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 주입을 쉽게 할 수 있습니다.
Kai

4
쿼리 문자열의 모든 변수 (있는 경우)가 코드 상수 또는 다른 안전한 소스에서 온다는 것을 알고있는 한 괜찮습니다. 예를 들어 createTable("MyTable"); OP의 질문은 코드에 직접 여러 줄 문자열 리터럴을 입력하는 방법에 관한 것 데이터베이스 쿼리 자체를 구성하는 방법이 아닙니다. :)
dbeachy1

2
더하기 (+) 수가 많은 경우 특히 문자열 빌더를 사용해야합니다.
gldraphael

8

@""를 사용할 수 있습니다 .

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

2
@는 그대로 문자열이고 ""는 큰 따옴표를 이스케이프하기 때문에 각각의 기능을 설명해야합니다.
AFract

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

여러 줄 추가 : @ 사용

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.