List 사용 시 주의할 점

2020. 2. 13. 01:18C#/제네릭

https://docs.microsoft.com/ko-kr/dotnet/api/system.collections.generic.list-1?view=netframework-4.8

 

List 클래스 (System.Collections.Generic)

 

인덱스에서 액세스할 수 있는 강력한 형식의 개체 목록을 나타냅니다.Represents a strongly t

docs.microsoft.com

List는 자료구조인 배열을 객체화시킨 클래스입니다. 표면적으로 들어난 장점은 크기를 지정할 필요없고 추가 데이터가 들어올 경우 자동으로 늘려줍니다.

private void Awake()
{
    ItemData[] datas = new ItemData[100];
    List<ItemData> items = new List<ItemData>();
 
    for (int i = 0; i < datas.Length; ++i)
    {
        items.Add(datas[i]);
    }
}
 
public class ItemData
{
    private int mCode;
}

하지만 위 코드는 크기에 비례하여 가비지를 발생합니다. List는 추가 데이터가 들어왔을 때 더 이상 담을 수 없다고 판단하면 기존 크기의 2배를 할당받습니다. 문제는 이 2배를 할당받는 방식인데 기존에 배치된 메모리 위치와 크기를 유지한 상태에서 추가적으로 부족한 메모리를 할당받아서 연결하는 것이 아니라 해당 크기의 2배의 메모리 공간을 찾아서 할당하는 방식입니다. 이 경우 기존의 크기는 그냥 버려지고 가비지 컬렉션의 수집 대상이 되어버립니다. 위의 코드가 심각한 것은 반복문을 돌면서 항목을 추가하기 때문에 다음과 같이 반복하면서 크기에 비례하여 가비지를 발생합니다.

 

항목 추가 -> 기존의 크기가 부족 -> 기존의 크기보다 2배의 공간을 할당 및 기존의 크기는 해제 대상으로 삼음 -> 항목 추가 -> 기존의 크기가 부족 -> 기존의 크기보다 2배의 공간을 할당 및 기존의 크기는 해제 대상으로 삼음 -> 반복

 

Capacity 설정

List에는 메모리를 미리 할당받을 수 있는 방법이 있는데 Capacity를 설정하여 미리 할당받을 수 있습니다. Capacity를 설정하는 방법은 List를 생성할 때 생성자의 매개인자에 할당받고자 하는 값을 설정하거나 생성 후 Capacity속성에 할당받고자 하는 값을 설정하는 방법으로 미리 할당받을 수 있습니다. 단 Capacity속성을 통해서 설정하는 것은 염두를 해두어야하는 점이 있는데 Capacity로 설정할 때마다 메모리를 할당받는 점입니다. 사용 방법은 다음 코드를 참고를 해주세요.

private void Awake()
{
    ItemData[] datas = new ItemData[100];
    List<ItemData> items = new List<ItemData>(datas.Length);
 
    for (int i = 0; i < datas.Length; ++i)
    {
        items.Add(datas[i]);
    }
}
 
public class ItemData
{
    private int mCode;
}
 

이렇게 설정하면 미리 할당받기 때문에 항목을 추가할 때 가비지가 발생할 걱정이 없어집니다. 추가적으로 예시를 들기 위해서 List로 언급했지만 Capacity를 가진 모든 컬렉션에 해당됩니다.

활용

아이템 인벤토리나 업적과 같이 List를 사용할 때 활용할 수 있습니다.