C#자료형은 값 형식과 참조 형식으로 나뉩니다. 이 둘의 차이는 데이터를 스택에 저장하느냐 아니면 힙에 저장하느냐에 따라 나뉩니다. 이번 포스팅에서는 각각의 자료형에 대한 특징과 사용법에 대해서 정리했습니다.
값 형식
값 형식은 변수가 실제 데이터 값을 저장하는 형식입니다. 값 형식을 갖는 자료형에는 c#의 기본 자료형과 열거형, 구조체가 있습니다. 이들 자료형들에 대한 데이터는 기본적으로 스택에 저장합니다. 다음은 값 형식에 대한 자료형들을 보여줍니다.
C# 값 형식 | 기본 C#형식(int, double, char, bool, float 등), struct, enum |
값 형식을 함수의 인자로 전달할 때 내부에서 변수값을 변경해도 원본의 변수값은 변하지 않습니다. 이러한 특징은 다음 예제롤 통해 확인할 수 있습니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace valueAndReference
{
internal class Program
{
public static void TestVaueType(int a)
{
a += 10;
}
static void Main(string[] args)
{
int value = 20;
Console.WriteLine(value);
TestVaueType(value); // value 원본값은 변하지 않는다.
Console.WriteLine(value);
}
}
}
결과
20
20
참조 형식
참조 형식은 변수가 값이 저장되어 있는 곳의 위치를 저장하는 형식입니다. 이것을 참조(reference)라고도 부릅니다. c++에서의 참조와 기능적으로 유사합니다. c#에서 참조 형식을 갖는 자료형은 다음과 같습니다.
C# 참조 형식 | object, string, dynamic, class, interface, delegate, 배열 |
string을 제외한 위 자료형들을 함수의 인자로 전달할 때 함수 내부에서 변수값이 수정된다면 원본의 값도 수정이 됩니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace valueAndReference
{
internal class Program
{
public static void TestRefType(int[] array)
{
array[0] = 1111;
}
static void Main(string[] args)
{
int[] arr = { 10, 20, 30, 40 };
Console.WriteLine(arr[0]);
TestRefType(arr); // value 원본 값이 변한다.
Console.WriteLine(arr[0]);
}
}
}
결과
10
1111
ref 키워드
값 형식의 자료형도 참조로 전달할 수 있습니다. 이때 사용하는 것이 ref 키워드입니다. 선언하는 곳과 사용하는 곳에 ref 키워드를 붙여야 합니다. 다음은 첫 번째 예제를 이용하여 ref키워드를 사용하는 방법을 보여줍니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace valueAndReference
{
internal class Program
{
public static void TestVaueType(ref int a)
{
a += 10;
}
static void Main(string[] args)
{
int value = 20;
Console.WriteLine(value);
TestVaueType(ref value); // value 원본값이 변경됩니다.
Console.WriteLine(value);
}
}
}
결과
20
30
값 형식처럼 행동하는 String
여기서 한 가지 더 언급할 것이 있습니다. 바로 string타입입니다. string은 분명 참조로 구분됩니다. 왜냐 하면 문자열 생성 시 힙에 생성을 하기 때문입니다. 하지만 string의 행동을 보면 마치 값 형식처럼 행동합니다. 그래서 그냥 string 타입을 함수의 인자로 전달하면 내부에서 수정 시 원본값이 변하지 않습니다. 참조로 쓰고 싶으면 값 형식처럼 ref 키워드를 써야 합니다. string의 이러한 성질은 불변성(immutable) 성에서 기인합니다. 한번 만들면 값을 변경할 수 없기 때문에 string 객체가 변경될 때마다 새로운 힙 영역에 객체를 만듭니다. 이것은 마치 복사본이 생성되는 값 형식처럼 보이게 만드는 원인이 됩니다.
다음은 string에 대한 값 형식과 참조형식을 보여주는 예제입니다.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading.Tasks;
namespace valueAndReference
{
internal class Program
{
public static void TestVaueString(string s)
{
s = "String is value type!";
}
public static void TestRefString(ref string s)
{
s = "String is ref type!";
}
static void Main(string[] args)
{
string str = "What type is String?";
Console.WriteLine(str);
TestVaueString(str);
Console.WriteLine(str);
TestRefString(ref str);
Console.WriteLine(str);
}
}
}
결과
What type is String?
What type is String?
String is ref type!
[참고]
1. "초보자를 위한 C# 200제(2판)" / 저자 : 강병익
2. C# 교과서 / 박용준 지음
3. microsoft c# 메뉴얼 : https://learn.microsoft.com/ko-kr/dotnet/csharp/
'Program Language > C#' 카테고리의 다른 글
Part1. C# 첫발 내딛기(29. default를 이용한 변수 초기화) (8) | 2023.01.26 |
---|---|
Part1. C# 첫발 내딛기(28. Null 조건 연산자 '?') (4) | 2023.01.24 |
Part1. C# 첫발 내딛기(26. const 와 readonly) (14) | 2023.01.20 |
Part1. C# 첫발 내딛기(25. String과 StringBuilder의 차이) (4) | 2023.01.20 |
Part1. C# 첫발 내딛기(24. String.Format()) (14) | 2023.01.18 |
댓글