[c#] 더하기 기호를 사용할 때 얼마나 많은 String 객체가 생성됩니까?

아래 코드에서 더하기 기호를 사용하면 몇 개의 String 객체가 생성됩니까?

String result = "1" + "2" + "3" + "4";

다음과 같으면 “1”, “2”, “12”의 세 가지 String 개체를 말했을 것입니다.

String result = "1" + "2";

또한 성능 향상을 위해 String 개체가 String Intern Pool / Table에 캐시된다는 것을 알고 있지만 그게 문제가 아닙니다.



답변

놀랍게도 상황에 따라 다릅니다.

메소드에서이 작업을 수행하는 경우 :

void Foo() {
    String one = "1";
    String two = "2";
    String result = one + two + "34";
    Console.Out.WriteLine(result);
}

그런 다음 컴파일러는 String.Concat@Joachim이 대답 한대로 코드를 내 보냅니다 (+1은 btw).

상수 로 정의하는 경우 , 예 :

const String one = "1";
const String two = "2";
const String result = one + two + "34";

또는 원래 질문에서 와 같이 리터럴 로 :

String result = "1" + "2" + "3" + "4";

그러면 컴파일러는 이러한 +신호를 최적화 합니다. 다음과 동일합니다.

const String result = "1234";

또한 컴파일러는 불필요한 상수 식을 제거하고 사용되거나 노출 된 경우에만 내 보냅니다. 예를 들어,이 프로그램은 :

const String one = "1";
const String two = "1";
const String result = one + two + "34";

public static void main(string[] args) {
    Console.Out.WriteLine(result);
}

문자열 하나만 생성합니다. 상수 result( “1234”와 같음). one그리고 two그 결과 IL에 표시되지 않습니다.

런타임에 추가 최적화가있을 수 있습니다. 나는 IL이 생산 되는대로 가고 있습니다.

마지막으로 인턴과 관련하여 상수와 리터럴이 인턴되지만 인턴 된 값은 리터럴이 아닌 IL의 결과 상수 값입니다. 즉, 여러 개의 동일하게 정의 된 상수 또는 리터럴이 실제로 동일한 개체가되기 때문에 예상보다 더 적은 수의 문자열 개체를 얻을 수 있습니다! 이것은 다음과 같이 설명됩니다.

public class Program
{
    private const String one = "1";
    private const String two = "2";
    private const String RESULT = one + two + "34";

    static String MakeIt()
    {
        return "1" + "2" + "3" + "4";
    }

    static void Main(string[] args)
    {
        string result = "1" + "2" + "34";

        // Prints "True"
        Console.Out.WriteLine(Object.ReferenceEquals(result, MakeIt()));

        // Prints "True" also
        Console.Out.WriteLine(Object.ReferenceEquals(result, RESULT));
        Console.ReadKey();
    }
}

문자열이 루프에서 (또는 그렇지 않으면 동적으로) 연결되는 경우 연결 당 하나의 추가 문자열로 끝납니다. 예를 들어 다음은 12 개의 문자열 인스턴스를 만듭니다. 상수 2 개 + 반복 10 개로 각각 새 String 인스턴스가 생성됩니다.

public class Program
{
    static void Main(string[] args)
    {
        string result = "";
        for (int i = 0; i < 10; i++)
            result += "a";
        Console.ReadKey();
    }
}

그러나 (또한 놀랍게도) 여러 연속 연결이 컴파일러에 의해 단일 다중 문자열 연결로 결합됩니다. 예를 들어,이 프로그램은 12 개의 문자열 인스턴스 만 생성합니다! 이는 ” 하나의 문에 여러 + 연산자를 사용하더라도 문자열 내용이 한 번만 복사 되기 때문 입니다.

public class Program
{
    static void Main(string[] args)
    {
        string result = "";
        for (int i = 0; i < 10; i++)
            result += "a" + result;
        Console.ReadKey();
    }
}


답변

Chris Shain의 대답은 매우 좋습니다. 문자열 연결 최적화 프로그램을 작성한 사람으로서 두 가지 흥미로운 점을 추가 할 것입니다.

첫 번째는 연결 최적화 프로그램이 안전하게 수행 할 수있을 때 기본적으로 괄호와 왼쪽 연관성을 모두 무시한다는 것입니다. 문자열을 반환하는 M () 메서드가 있다고 가정합니다. 당신이 말하는 경우:

string s = M() + "A" + "B";

그런 다음 컴파일러는 더하기 연산자가 연관성으로 남아 있기 때문에 다음과 같습니다.

string s = ((M() + "A") + "B");

하지만 이것은:

string s = "C" + "D" + M();

와 같다

string s = (("C" + "D") + M());

그래서 그것은 상수 문자열 "CD"M().

사실, 연결 최적화는 문자열 연결이 실현 연관 및 생성 String.Concat(M(), "AB")이 왼쪽 연관성을 위반하더라도, 최초의 예를 들어.

다음과 같이 할 수도 있습니다.

string s = (M() + "E") + ("F" + M()));

그리고 우리는 여전히 String.Concat(M(), "EF", M()).

두 번째 흥미로운 점은 null 및 빈 문자열이 최적화된다는 것입니다. 따라서 이렇게하면 :

string s = (M() + "") + (null + M());

당신은 얻을 것이다 String.Concat(M(), M())

흥미로운 질문이 제기됩니다. 이건 어떨까요?

string s = M() + null;

우리는이를 최적화 할 수 없습니다.

string s = M();

때문에 M()null을 반환 할 수 있지만 null String.Concat(M(), null)을 반환하면 빈 문자열을 반환M() 입니다. 그래서 우리가하는 일은

string s = M() + null;

string s = M() ?? "";

따라서 문자열 연결이 실제로 전혀 호출 할 필요가 없음을 보여줍니다 String.Concat.

이 주제에 대한 자세한 내용은 다음을 참조하십시오.

String.Concat이 StringBuilder.Append에 최적화되지 않은 이유는 무엇입니까?


답변

MSDN에서 답을 찾았습니다. 하나.

방법 : 여러 문자열 연결 (C # 프로그래밍 가이드)

연결은 한 문자열을 다른 문자열 끝에 추가하는 프로세스입니다. + 연산자를 사용하여 문자열 리터럴 또는 문자열 상수를 연결하면 컴파일러에서 단일 문자열을 만듭니다. 런타임 연결이 발생하지 않습니다. 그러나 문자열 변수는 런타임에만 연결할 수 있습니다. 이 경우 다양한 접근 방식이 성능에 미치는 영향을 이해해야합니다.


답변

딱 하나만. C # 컴파일러는 문자열 상수를 접으므로 기본적으로 다음과 같이 컴파일됩니다.

String result = "1234";


답변

나는 이것이 어떤 표준이나 사양에 의해 의무화되어 있는지 의심합니다. 한 버전은 다른 버전과 다른 작업을 수행 할 수 있습니다.


답변

하나는 정적이기 때문에 컴파일러는 컴파일 타임에 단일 문자열로 최적화 할 수 있습니다.

동적 이었다면 String.Concat (string, string, string, string) 에 대한 단일 호출에 최적화되었을 것 입니다.


답변