C++ 쟁이가 C#을 배워보자 - 문자열 string
C# 관련 첫 포스트인 "C++ 쟁이가 C#을 배워보자 - 변수" 편을 보면 null 값 항목에 다음과 같은 내용이 있다.
위와 같은 코드를 실행하더라도 정수형 변수 val이 Call by Value 형태로 메서드 foo에 전달되었기 때문에 foo 내부에서 변경한 값이 WriteLine 출력시 반영되지 않는다. 즉, foo에서 i++한 내용은 foo 내부에서만 유효하다.
자, 그렇다면 string 타입은 어떤가? 분명히 서두에 string은 참조 타입이라고 기술하였으므로 메서드의 파라미터로 넘길 때 Call by Reference로 넘어가고, 메서드 내부에서 문자열을 조작하면 바뀔 것이라고 추측이 가능하다.
삐빅! 틀렸습니다!
왜 그럴까요? 그렇다면 "Hello World"가 출력되는 것일까? 으아니 도대체 무슨 일이 벌어진게야!!
C#의 string은 불변하는 성질을 가지고 있다. 즉, 한번 생성된 이후에는 바꿀 수 없다는 의미. 그러나 바꿀 수 있어 보이긴 하는데? 어떻게 되는걸까?
string 관련 메서드 및 연산은 해당 변수의 문자열에 직접적인 조작이나 변경이 가해지는 것이 아니라, 조작된 문자열을 가지는 새로운 문자열을 생성한다. 새 문자열은 지정한 변수에 할당 된다.
string은 이러한 불변의 성질을 가지고 있기 때문에 메서드의 파라미터로 넘어가더라도 값의 형태로 넘어가게 되어 있어서 메서드 내부에서의 변경이 메서드 바깥쪽까지 영향을 미치지 못한다.이 포스트의 윗쪽에 있는 fooString 메서드를 의도한대로 작동하도록 하려면 ref 키워드를 사용하여 Call by Reference로 넘겨야 한다.
기본 타입에서 string을 제외한 타입은 값 타입이기 때문에 반드시 값을 가져야 함. (string은 참조 타입이라 null 가능)C++과 달리 C#에서는 포인터 타입을 직접적으로 다루지 않는다. (물론 unsafe 키워드를 사용하여 다룰수는 있지만 그다지 권장되지는 않는다.)또한 자바와 유사하게 메서드 호출 시 string을 제외한 기본 타입 및 struct 타입은 값(value type) 형태로 넘어가게 되어 메서드 내부에서 변수의 값을 변경해도 메서드 호출부까지는 변경 내용이 전달되지 않는다.
void foo(int i) { i++; } int val = 100; foo(val); //foo에서 값을 1 증가 시켰지만 WriteLine으로는 100이 출력됨 System.Console.WriteLine($"{val}");
위와 같은 코드를 실행하더라도 정수형 변수 val이 Call by Value 형태로 메서드 foo에 전달되었기 때문에 foo 내부에서 변경한 값이 WriteLine 출력시 반영되지 않는다. 즉, foo에서 i++한 내용은 foo 내부에서만 유효하다.
자, 그렇다면 string 타입은 어떤가? 분명히 서두에 string은 참조 타입이라고 기술하였으므로 메서드의 파라미터로 넘길 때 Call by Reference로 넘어가고, 메서드 내부에서 문자열을 조작하면 바뀔 것이라고 추측이 가능하다.
void fooString(string str) { str = "Hello 써냉"; } string org = "Hello World"; fooString(org); System.Console.WriteLine(org);
삐빅! 틀렸습니다!
왜 그럴까요? 그렇다면 "Hello World"가 출력되는 것일까? 으아니 도대체 무슨 일이 벌어진게야!!
C#의 string은 불변하는 성질을 가지고 있다. 즉, 한번 생성된 이후에는 바꿀 수 없다는 의미. 그러나 바꿀 수 있어 보이긴 하는데? 어떻게 되는걸까?
string 관련 메서드 및 연산은 해당 변수의 문자열에 직접적인 조작이나 변경이 가해지는 것이 아니라, 조작된 문자열을 가지는 새로운 문자열을 생성한다. 새 문자열은 지정한 변수에 할당 된다.
//MSDN 샘플코드 string s1 = "Hello "; string s2 = s1; s1 += "World"; System.Console.WriteLine(s2);위 코드를 실행하면 Hello 가 출력이 된다. 수행되는 과정을 살펴보면 다음과 같다
- s1에 문자열 "Hello " 할당
- s2는 s1이 가리키고 있는 "Hello "를 할당
- s1는 원래 가지고 있던 "Hello "와 "World"를 더하여 생성된 "Hello World"를 할당
- s2에 할당한 "Hello " 문자열은 여전히 유효하고 내용이 변경되지 않았으므로 콘솔창에 "Hello " 출력
string은 이러한 불변의 성질을 가지고 있기 때문에 메서드의 파라미터로 넘어가더라도 값의 형태로 넘어가게 되어 있어서 메서드 내부에서의 변경이 메서드 바깥쪽까지 영향을 미치지 못한다.이 포스트의 윗쪽에 있는 fooString 메서드를 의도한대로 작동하도록 하려면 ref 키워드를 사용하여 Call by Reference로 넘겨야 한다.
void fooString(ref string str) { str = "Hello 써냉"; } string org = "Hello World"; fooString(ref org); System.Console.WriteLine(org);아니면 직접 조작이 가능한 StringBuilder로 문자열을 처리하면 된다. 또한 조작이 빈번한 경우 string보다 StringBuilder로 작업을 하는 것이 성능상 잇점이 있다.
댓글
댓글 쓰기