string
string은 값이 텍스트인 자료형이다. string의 내부는 char 개체가 순차적으로 저장된 형태이다. 즉 char의 배열로 이루어져 있다.
C언어에서는 문자열이 null문자로 끝나는 문자 배열이다. 즉 Hello를 저장하면 'H' 'e' 'l' 'l' 'o' '\0'로 저장된다. 하지만 C#에서는 문자열이 null 문자로 끝나지 않는다. C#의 문자열은 자동으로 메모리 관리를 처리하며 null 문자에 대한 직접적인 관리를 하지 않아도 된다. 그래서 문자열의 길이를 알고 싶을 땐 Length 속성을 통해 확인할 수 있다.
string의 불변성
C#에서는 string이 매우 중요하다. 그 이유는? string이 가비지 컬렉터에 부담이 되기 때문이다. 왤까? 바로 string의 불변성 이라는 속성 때문이다.
C#에서 string이 생성되면 그 개체는 변경할 수 없다. 문자열 개체를 만든 후에는 그 문자열 변경이 불가능하다. 만약 코드상에서 string 변수를 만들고 문자열1을 저장했다고 치자. 그리고 그 변수에 다시 문자열2를 저장해 수정했다면, 그것은 실제로 문자열1을 문자열2로 바꾼 것이 아니라 새로운 문자열2 개체가 힙 영역에 만들어지는 것이다. 문자열에 + 연산을 하여 문자열을 합치는 과정도 마찬가지다. 그래서 C#에서 string 수정은 실제로 새 문자열을 만드는 것이므로 문자열에 대한 참조를 만들 때 주의해야 한다.
이렇게 광범위한 문자열 조작(예: 루프에서 문자열을 여러 번 수정하는 앱)을 수행하는 루틴의 경우 문자열을 반복적으로 수정하면 상당한 성능 저하가 발생될 수 있다.
그렇다면 string의 불변성에 대항할 대비책은 무엇이 있을까? 대표적으로 StringBuilder가 있다.
StringBuilder
StringBuilder는 변경할 수 있는 문자열이다. StringBuilder는 문자열을 더할 때 새로운 객체를 생성하는 것이 아니라 기존의 문자열 데이터에 더하는 방식을 사용하기 때문에 속도도 빠르고 상대적으로 부하가 적다. 그래서 StringBuilder는 빈번히 긴 문자열들을 더해야 할 경우에 효과적이다.
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("world");
이런식으로 스트링빌더에 있는 append 함수로 문자열을 더할 수 있다. 다 더해진 sb를 출력하기 위해서는 sb의 ToString()을 호출하여 출력해야 한다.
다만 StringBuilder는 문자열 변경을 빈번하게 사용할 코드에 활용하는 것이 좋다. 코드에서 문자열에 적용할 변경 횟수가 작은 경우 이러한 경우에 StringBuilder에 비해 String성능이 미미하거나 개선되지 않을 수 있다.
StringBuilder 작동 방식
그렇다면 StringBuilder는 어떻게 구성되어 있고 어떻게 작동하는 걸까? (List와 굉장히 비슷하다.)
StringBuilder 인스턴스의 길이를 나타내는 StringBuilder.Length는 현재 인스턴스에 포함되는 문자 수를 가리킨다. 이 개체에 StringBuilder 문자를 추가하면 개체에 포함될 수 있는 문자 수를 정의하는 속성인 StringBuilder.Capacity 크기와 같을 때까지 길이가 증가한다.
만약 Capacity 크기에 초과한다면 새 메모리가 할당되고 속성값 Capacity는 두 배로 증가한다. 그리고 새 문자가 개체에 StringBuilder 추가되고, 해당 Length속성이 조정된다.
StringBuilder는 MaxCapacity라는 속성이 있다. 새 메모리에 할당 되어도 StringBuilder 자체에 있는 최대 수용값인데, 개체에 대한 추가 메모리는 이 값에 도달할 때까지 동적으로 할당된다. 최대 용량에 도달하면 더 이상 메모리를 StringBuilder로 할당할 수 없으며 최대 용량을 초과하려 하면 예외 사항이 발생하게 된다.
출처: https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/strings/
'C#' 카테고리의 다른 글
[C#] 델리게이트(delegate), 이벤트(event) (0) | 2023.11.13 |
---|---|
[C#] 코루틴(Coroutine) (0) | 2023.11.13 |
[C#] 정렬(Sorting) (0) | 2023.11.13 |
[C#] Hashtable(해시 테이블), Dictionary(딕셔너리) (2) | 2023.11.13 |
[C#] 박싱(Boxing), 언박싱(Unboxing) (1) | 2023.11.13 |