다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.
2021.04.12 - [기술 면접용 질문들/프로그래밍 관련] - 박싱(Boxing) vs 언박싱(Unboxing)
박싱 & 언박싱
- 값 타입을 참조타입으로 변경(박싱), 참조 타입을 값 타입으로 변경(언박싱)하는 것을 말한다.
- 박싱과 언박싱을 수행하는 과정에서 복사가 일어나 임시 객체가 생성되기도 하며, 불필요한 가비지가 남아 성능에 좋지않은 영향을 미친다.
- 대부분 .NET 2.0에 추가된 제네릭 클래스와 메서드를 사용하면 박싱과 언박싱을 피할 수 있다.
대표적인 박싱 예 : 보간문자열
- 보간문자열은 내부적으로 System.Object 객체에 대한 배열로 인자를 받는다.
- 때문에 값 타입인 number 변수를 System.Object 타입으로 박싱한 뒤, 박싱된 객체에 ToString()메서드를 호출한다.
int number = 1;
Console.WriteLine($"myNumber : {number}");
- 내부적으로는 아래의 코드와 유사하다고 볼 수 있다.
- object에 대한 ToString()은 또다시 언박싱을 필요로 할테니, 의미없이 박스에 싸고 다시 박스를 푸는 형태가 된다.
int number = 1;
object o = number;
Console.WriteLine($"myNumber : {o.ToString()}");
- 결론적으로 값 형식을 보간문자열의 인자로 사용할 경우 ToString()메소드를 직접 호출한다면 System.Object로 변환되는 것을 막을 수 있다.
int number = 1;
Console.WriteLine($"myNumber : {number.ToString()}");
컬렉션과 박싱
- .NET 1.x의 컬렉션은 System.Object 타입의 객체의 참조를 저장한다.
- 값 타입을 컬렉션에 추가할 때는 박싱이 일어난다.
- 값 타입의 객체를 사용한다면, 값을 사용할 때마다 박싱된 객체의 복사본을 가져온다.
컬렉션 내 구조체 값 변경
- 구조체는 값 타입이다.
- 구조체가 리스트 내에 있을 경우 값을 바로 변경하려고하면 컴파일 오류가 발생한다. (임시 객체는 수정할 수 없다)
- 리스트 내부에서 원소를 가져오는 순간 새로운 복사본이 생성된다.
- 구조체의 배열의 값은 바로 변경이 가능하다. (속성이 ref로 선언되어있다)
public List<MyStruct> myList = new List<MyStruct>();
public MyStruct[] myArray = new MyStruct[3];
public MyStruct mySt;
public void Setup()
{
myList.Add(new MyStruct());
var temp = myList[2]; // 참조가 아니라 복사본을 생성하였다.
temp.name = "my"; // 원본에는 영향을 주지 않는다.
myArray[2].name = "my"; // 원본 값이 바뀐다.
mySt.name = "my"; // 원본 값이 바뀐다.
}
결론
- 박싱과 언박싱은 자동으로 일어나기 때문에 주의해야하며,
.NET 2.0에서 추가된 제네릭 클래스와 메서드를 사용하자.
'🌍 C# Study > 이펙티브 C#' 카테고리의 다른 글
[11] .NET 리소스 관리에 대한 이해 (0) | 2021.04.25 |
---|---|
[10] 베이스 클래스가 업그레이드된 경우에만 new 한정자를 사용하라 (0) | 2021.04.23 |
[08] 이벤트 호출 시에는 null 조건 연산자를 사용하라 (0) | 2021.04.23 |
[07] 델리게이트를 이용하여 콜백을 표현하라 (0) | 2021.04.23 |
[06] nameof() 연산자를 적극 활용하라 (0) | 2021.04.22 |