안녕하세요. 박민성입니다. 🤗
오늘은 C#에 문자열(String)에 대해서 글을 쓰고자 합니다. 🤔
string에 경우에 모르는 사람은 없겠지만 string을 더 자세하게 알아보기 위해서
string에 관해서 글을 쓰게 되었습니다.
string을 모르시는 분은 없다고 생각하고 진행하겠습니다.
1. string과 System.String의 관계
string first = "Hello";
System.String second = "World";
둘은 같은 타입입니다.
string은 C#에서 System.String을 간단하게 작성할 수 있도록 제공하는 키워드 같은 것입니다.
System.String은 클래스이기 때문에 string은 참조 형식입니다.
개념적으로 first변수는 "Hello"라는 문자열 객체를 가리키는 참조를 가지고 있습니다.
다만 string은 일반적인 클래스와 조금 차이점이 있는데요.
1. 문자열(string)은 불변 개체입니다.
2. == 연산자가 문자열의 내용을 비교하도록 구현되어 있습니다.
2. 문자열의 불변성이란?
불변 객체란 한 번 생성된 후 내부 상태를 변경할 수 없는 객체를 의미합니다.
string text = "Hello";
text += " World";
이 코드는 "Hello" 뒤에 " World"가 추가되어 기존 문자열이 바뀐 것처럼 보이지만.
실제로는 문자열 객체의 내용이 바뀐 것이 아니라, 변수가 가리키는 문자열을 바뀐 것입니다.
기존에 text = "Hello";는 바뀌지 않고 "HelloWorld"라는 문자열 객체가 생성됩니다.
문자열의 불변성을 직접 확인 해볼 수도 있습니다.
string text = "Hello";
char character = text[0];
이런식으로 문자열의 있는 문자를 읽는 것은 가능하지만
string text = "Hello";
text[0] = 'Y'; // 컴파일 오류
이렇게 문자열의 있는 문자 요소를 수정할 수는 없습니다;;
그렇기 때문에 문자열을 만들었을 때
값을 바꾸는 것이 아닌 +=할 때는 새로운 string객체를 생성하는 것입니다.
3. 문자열의 == 비교
일반 클래스에서는 ==가 기본적으로 같은 객체를 가리키는지 확인합니다. 그래서 클래스 주소 비교를 하는데요.
하지만 문자열의 ==는 문자열 내용을 비교하도록 정의되어 있습니다.
string first = new string(new[] { 'H', 'i' });
string second = new string(new[] { 'H', 'i' });
Console.WriteLine(first == second);
이러면 first와 second의 내용이 같기 때문에 true가 나옵니다.
여기서 같은 객체인지 확인하고 싶다면 ReferenceEquals를 사용하시면 됩니다.
4. 문자열 결합 시 일어나는 일
문자열은 불변이므로 런타임의 문자열 값을 결합할 때는 기존 문자열을 늘리는 것이 아니라, 결합 결과를 표현할 문자열이 필요합니다. 그래서 +를 사용 시에 새로운 객체가 생성되지만...
string text = "Hello" + " World";
하지만 이런 코드에서는 컴파일러가 미리 "Hello World"로 합칠 수 있습니다.
+를 한 번 사용할 때마다 무조건 새로운 문자열 객체가 생기는 것이 아닌
실행 중 결정되는 문자열을 결합하면 기존 문자열의 내용이 수정되는 것이 아니라, 결합 결과를 나타내는 문자열이 만들어지는 것입니다.
5. 반복문에서 문자열 결합
string result = "";
for (int i = 0; i < 1000; i++)
{
result += i;
}
이런 식으로 코드를 작성하게 된다면 결과가 "0", "01", "012", "0123" 이렇게 커집니다.
이럴 때는 StringBuilder를 사용하는 것이 좋습니다.
StringBuilder는 Append로 내부 내용을 변경하며 누적이 가능한데요.
StringBuilder에 내용을 다 담고 나서 ToString()을 사용해서 내부 내용을 string으로 바꾸면 됩니다.
6. null, 빈 문자열, 공백 문자열
string nullText = null;
string emptyText = "";
string whiteSpaceText = " ";
여기서 문자열들은 다 다른 것을 의미 하는데요.
nullText는 문자열 참조가 없다는 뜻이고
emptyText는 길이가 0인 문자열이라는 뜻이고
whiteSpaceText는 공백 문자를 포함한 문자열이라는 뜻입니다.
저는 그동안 nullText랑 emptyText가 비슷하다고 생각하고 별 생각없이 사용했었는데
살짝 신기하네여;;
검사는
string.IsNullOrEmpty(text);
string.IsNullOrWhiteSpace(text);
이런식으로 할 수가 있습니다.
7. 문자열 리터럴, 이턴닝이란?
string text = "Hello";
코드에 직접 작성한 문자열을 문자열 리터럴이라고 합니다. (여기서는 "Hello"가 리터럴입니다.)
문자열 이터닝이란 내용이 같은 문자열 리터럴을 하나의 문자열 객체로 공유하는 방식을 뜻합니다.
string first = "Hello";
string second = "Hello";
이런식으로 코드에는 "Hello"가 두 번 작성됐지만 런타임은 같은 내용의 문자열 객체를 두 개 만들 필요가 없다고 판단하고
리터럴이 겹치는 객체는 추가로 생성하지 않고 같은 주소를 가리키게 됩니다. 이것을 문자열 이터닝이라고 합니다.
그렇게 런타임이 인터닝된 문자열들을 관리하는 공간을 가지고 있는데요.
이를 보통 인터닝 풀이라고 부릅니다. 같은 문자열 리터럴이 이미 인터닝 풀에 있다면 기존 객체를 재사용합니다.
string first = "Hello";
string second = new string(new[] { 'H', 'e', 'l', 'l', 'o' });
하지만 이런식으로 런타임에 만들어진 문자열들은
내용이 같다고 해도 서로 다른 객체를 가리키고 있을 수 있습니다.
내용이 같다고 자동으로 모든 문자열 객체가 하나로 합쳐지는 것은 아니라는거죠.
그 이외에도 문자열 결합 결과는 인터닝이 될까?, const string도 인터닝되는가?, 직접 이터닝 하는 법, 왜 모든 문자열을 자동으로 인터닝하지 않을까?, 문자열 리터럴은 언제 사라질까?는 글 내용이 너무 길어저서 따로 다루지는 않겠지만 나중에 때가 된다면
더 자세히 다뤄보겠습니다. 지금은 그냥 "이런게 있구나~"하고 넘어가겠습니다....
이상으로 C# 문자열(string)에 대해서 알아보았는데요~!
문자열을 바꿀때 새로운 객체를 생성될 수도 있는만큼 GC 때문에 조심히 써야 하는데여...
생각없이 막 쓰다가 골로 갈 수 있는 것을 배웠습니다... 🤕
오늘도 굉장히 알찬 하루였습니다. ☺️
내일은 더욱 알차게 보내고 작성해보도록 하겠습니다.
봐주셔서 감사합니다. ☺️