아래 코드에서 더하기 기호를 사용하면 몇 개의 String 객체가 생성됩니까?
String result = "1" + "2" + "3" + "4";
다음과 같으면 "1", "2", "12"의 세 가지 String 개체를 말했을 것입니다.
String result = "1" + "2";
또한 성능 향상을 위해 String 개체가 String Intern Pool / Table에 캐시된다는 것을 알고 있지만 그게 문제가 아닙니다.
아래 코드에서 더하기 기호를 사용하면 몇 개의 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();
}
}
string s = ""; for (int i = 0; i < n; i++) s += "a";
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
.
이 주제에 대한 자세한 내용은 다음을 참조하십시오.
("C" + "D") + M())
생성 String.Concat("CD", M())
, 없습니다 String.Concat(M(), "AB")
. 그리고 더 아래, (M() + "E") + (null + M())
생성해야 String.Concat(M(), "E", M())
하지 String.Concat(M(), M())
.
MSDN에서 답을 찾았습니다. 하나.
방법 : 여러 문자열 연결 (C # 프로그래밍 가이드)
연결은 한 문자열을 다른 문자열 끝에 추가하는 프로세스입니다. + 연산자를 사용하여 문자열 리터럴 또는 문자열 상수를 연결하면 컴파일러에서 단일 문자열을 만듭니다. 런타임 연결이 발생하지 않습니다. 그러나 문자열 변수는 런타임에만 연결할 수 있습니다. 이 경우 다양한 접근 방식이 성능에 미치는 영향을 이해해야합니다.
나는 이것이 어떤 표준이나 사양에 의해 의무화되어 있는지 의심합니다. 한 버전은 다른 버전과 다른 작업을 수행 할 수 있습니다.
하나는 정적이기 때문에 컴파일러는 컴파일 타임에 단일 문자열로 최적화 할 수 있습니다.
동적 이었다면 String.Concat (string, string, string, string) 에 대한 단일 호출에 최적화되었을 것 입니다.