04
23
다음 본문은 도서 이펙티브 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에서 추가된 제네릭 클래스와 메서드를 사용하자.

 

 

 

 

COMMENT