본문 바로가기

관리 메뉴

[C#] Generic Parameter Call By Value, Call By Reference 본문

프로그래밍/ㄴ기타

[C#] Generic Parameter Call By Value, Call By Reference

최갓 2023. 5. 18. 11:06
반응형

Generic Type의 변수를 Function의 Parameter로 넘긴 후, Function내에서 해당 Parameter를 init한다고 해도, Function의 stack을 탈출하면 해당 parameter는 null이 된다.

 

이 이유는 Generic Type의 변수는 값에 의한 전달이 이루어지기 때문이다(클래스의 경우라도)

 

C#에서 제네릭(Generic) 타입으로 변수를 전달할 때, 값에 의한 전달(Call by Value)이 이루어지는 이유는 C#의 설계 결정 사항 중 하나입니다.

C#에서 제네릭은 일반적으로 컴파일 시간에 타입을 결정하는 방식으로 동작합니다. 이는 제네릭 타입에 대한 코드를 생성할 때 컴파일러가 실제로 사용될 타입에 대한 복사본을 만들어 사용한다는 것을 의미합니다. 이러한 복사본은 각각의 메서드 또는 함수에 대해 별개로 생성되며, 각각의 복사본은 자체적으로 값에 의한 전달(Call by Value)으로 동작합니다.

이러한 설계 결정은 다음과 같은 이유로 이루어졌습니다:

  1. 유연성: 제네릭 타입을 값에 의한 전달로 처리함으로써 여러 메서드에서 동일한 제네릭 타입 인자를 사용할 수 있습니다. 이는 제네릭 코드의 재사용성과 유연성을 높여줍니다.
  2. 안정성: 값에 의한 전달은 각각의 제네릭 인스턴스에 대해 독립적인 복사본을 만들어 사용하므로, 제네릭 타입이 예상치 않은 부작용을 일으킬 가능성을 줄여줍니다. 제네릭 인스턴스가 서로 다른 메모리 공간을 사용하므로, 한 인스턴스의 수정이 다른 인스턴스에 영향을 미치지 않습니다.
  3. 성능: 값에 의한 전달은 메모리 복사를 수반하지만, 일반적으로 제네릭 타입에 대한 작은 객체를 전달하는 것은 성능에 큰 영향을 주지 않습니다. 값에 의한 전달은 메모리 액세스 패턴에 대한 최적화를 용이하게 하고, 메모리 관리를 단순화합니다.

이러한 이유로 C#에서는 제네릭 타입을 값에 의한 전달(Call by Value)로 처리합니다. 그러나 제네릭 타입의 메서드에 ref 키워드를 사용하면 변수에 대한 참조를 전달할 수 있으므로 Call by Reference로 동작하도록 할 수도 있습니다.

 

 

예시)

 public void MakeT()
    {
        G_UIBase vClassObject = null;
        InitT(vClassObject);

        Debug.Log(vClassObject);
        이때 vClassObject는 null이다.
    }

    private void InitT<T>(T vClass) where T : G_UIBase
    {
        GameObject vUIObject = CreateUI(G_Constant.m_stRUIAbilityGradeItemSlot, gameObject);
        vClass = vUIObject.GetComponent<T>();
    }

 

 

이를 해결하기 위해선 다음의 방법이 있다.

public void MakeT()
{
    G_UIBase vClassObject = null;
    InitT(ref vClassObject);

    Debug.Log(vClassObject);
}

private void InitT<T>(ref T vClass) where T : G_UIBase
{
    GameObject vUIObject = CreateUI(G_Constant.m_stRUIAbilityGradeItemSlot, gameObject);
    vClass = vUIObject.GetComponent<T>();
}

 

반응형
Comments