본문 바로가기
프로그래밍/C#

C# String은 참조 타입(Reference type)이면서 불변(Immutable)하다.

by bantomak 2024. 1. 10.

string vs StringBuilder

예를 들어, int의 경우를 살펴보자. int는 값 타입(value type)이면서 가변(mutable)이다.

값 유형(Value Type) 변수의 메모리 할당

 

값 타입은 데이터 변경 시에 새로운 메모리 할당이 일어나지 않는다. 이미 생성된 메모리의 데이터가 변경된다.

 

static void Main(string[] args)
{
    int a = 100;
    int b = a;

    a = 300;

    Console.WriteLine($"a : {a}"); // 300
    Console.WriteLine($"b : {b}"); // 100
}

 

string의 경우를 살펴보자. string은 참조 타입(reference type)이면서 불변(immutable)이다.

참조 유형(Reference Type) 변수의 메모리 할당

 

static void Main(string[] args)
{
    string s = "Hello World";
    string s1 = s;

    a = "World Hello"; // 메모리 재할당이 일어난다.

    Console.WriteLine($"a : {a}");  // "World Hello"
    Console.WriteLine($"b : {b}");  // "Hello World"
}

 

string 타입의 메모리 할당

 

참조 타입은 Heap memory에 할당된 주소를 가진다. 그렇다면 데이터 변경 시에 어떤 일이 일어나는 것일까?

string의 경우 가변처럼 작동하는 거 같지만 사실 내부적으로는 매번 메모리 할당이 일어나고 있다. 그래서 string을 매우 많이 변경하면 메모리에 오버헤드가 발생하게 된다.

(주로 string과 StringBuilder를 비교하면서 자주 언급되는 내용)

 

static void Main(string[] args)
{
    string s = "world";
    string s1 = s;

    s += "hello";  // 메모리 할당
    s += "1";      // 메모리 할당
    s += "2";      // 메모리 할당

    Console.WriteLine(s);  // "worldhello12"
    Console.WriteLine(s1); // "world"
}

 

string 객체가 참조하는 메모리가 달라지는 것이다. 값이 달라지면 새로 생성하고 해당 메모리를 참조한다.

 

string이 불변이라는 것에 의문을 제기하는 많은 질문 글들이 존재한다.

(불변이 맞다. 매번 새로 힙 영역에 할당되는 것이다.)

 

if strings are immutable in c#, how come I am doing this?

I read today, in c# strings are immutable, like once created they cant be changed, so how come below code works string str="a"; str +="b"; str +="c"; str +="d"; str +="e"; console.write(str) //ou...

stackoverflow.com

 

그렇다면 StringBuilder의 경우는 어떻게 다른가? StringBuilder는 참조 타입(reference type)이면서 가변(mutable)이다.

static void Main(string[] args)
{
    StringBuilder a = new StringBuilder();
    StringBuilder b = new StringBuilder();

    a.Append("1");
    b = a;

    a.Append("3");

    Console.WriteLine($"a : {a}"); // 13
    Console.WriteLine($"b : {b}"); // 13
}

 

StringBuilder의 경우 값이 달라지면 참조하는 메모리의 내용이 실제로 변경된다.

 

값 타입(Value Type)과 참조 타입(Reference Type) 분류

참고자료: 시작하세요! C# 7.3 프로그래밍

 

  • 하늘색으로 표현한 부분이 값 타입(Value Type)
  • 파란색으로 표현한 부분이 참조 타입(Reference Type)

System.ValueType, bool, byte, int, float, char, enum, struct로 정의하는 타입들이 값 타입(value Type)이다.

object, string, System.Array, class로 정의하는 타입들이 참조 타입(Reference Type)이다.

 

값 타입(Value Type)과 참조 타입(Reference Type) 동작 차이

C#에서는 왜 값 타입과 참조 타입을 구분하였을까?

 

  • 메모리가 작은 변수는 값을 복사하는게 빠르다.
  • 메모리가 큰 변수는 값이 아니라 주소를 복사하는 게 빠르고 효율적이다.

 

상대적으로 메모리가 클 가능성이 높은 참조 타입 변수의 복사는 값 복사가 아닌 주소값(4바이트, 8바이트)을 복사함으로써 메모리 주소를 복사한 것이지만 프로그래머는 이를 마치 전체 값이 복사된 것처럼 사용할 수 있다.

 

C++ 프로그래머의 경우 일반 객체와 포인터 객체를 구분해서 작성하지만 C#의 경우에는 프로그래머가 이에 대해 몰라도 코드를 작성하는데 아무 지장이 없다. (편의성 제공) 하지만 C# 내부 작동 개념을 알아야지 효율적인 프로그래밍이 가능할 것이다.

 

함께 읽으면 좋은 글

 

C# 가변(Mutable)과 불변(Immutable) 타입에 대하여

가변 타입과 불변 타입에 대해서 글자 그대로 변화가 가능한지(can change) 혹은 불가능 한지(can not change)를 표현한다. 그렇다면 어떤게 변하고 어떤게 변하지 않는다는 것일까? 가변(Mutable) - 동일

jettstream.tistory.com

 

리터럴(Literal)과 상수(Constant)에 대해서

리터럴(Literal) 리터럴(Literal)이란 소스 코드의 고정된 데이터를 의미한다. "리터럴이란 소스코드의 고정된 값을 대표하는 용어"라고 한다. "고정된 값 == 변하지 않는" 값을 말하며, 좀 더 쉽게 말

jettstream.tistory.com

 

참고 사이트

 

C# Value Type과 Reference Type

C#을 공부하다 보면 Value Type(값 형식)과 Reference Type(참조 형식)이라는 것을 듣게 됩니다. 이런 것들을 모르고 코딩해도 대체로 원하는 결과를 얻을 수 있습니다. 하지만 가끔가다 코드가 이해하기

mathmakeworld.tistory.com

 

Value Type and Reference Type

Value Type and Reference Type In C#, these data types are categorized based on how they store their value in the memory. C# includes the following categories of data types: Value type Reference type Pointer type Value Type A data type is a value type if it

www.tutorialsteacher.com

 

C# String VS StringBuilder | Top 5 Differences between string and StringBuilder - Shekh Ali's Blog

C# string vs stringbuilder: String is an immutable type, which means it can't be changed once it's been created. StringBuilder, on the other hand is mutable.

www.shekhali.com

댓글