레퍼런스 타입에 ref 를 사용하는 경우

[제목] 레퍼런스 타입에 ref 를 사용하는 경우

C# 키워드인 ref는 해당 Type 객체가 호출되는 메서드에서 변경될 수 있다는 의미한다. Value 타입의 객체의 경우 해당 값이 호출되는 메서드에서 변경될 수 있고, 이를 호출하는 쪽에서 사용하기 위해서는 ref를 반드시 사용해야 한다.

예를 들어, 아래 예제처럼 Sum()이라는 메서드가 3개의 파라미터를 받아들이는데, 이 3개를 모두 더한 값은 마지막 3번째 파라미터에 저장한 후 리턴한다고 하면, 3번째 파라미터에 ref를 붙여 사용해야 한다. 만약 ref를 사용하지 않는다면, Sum() 내부에서 변경된 부분은 호출 함수에서는 반영되지 않기 때문에, 결과는 30이 출력된다.

public void RunTest()
{
    int a = 10;
    int b = 20;
    int c = 30;
    bool success = Sum(a, b, ref c);
    Console.WriteLine(c);
}

public bool Sum(int a, int b, ref int sum)
{
    sum += a + b;
    return true;
}

그렇다면 레퍼런스 타입 객체는 전달할 때는 어떠한가? 레퍼런스 타입 객체는 Heap 영역의 포인터만 전달하기 때문의 ref를 사용하지 않아도 해당 객체의 프로퍼티나 객체 내용을 변경할 수 있다. 예를 들어, 아래 예제는 DataSet 레퍼런스 객체를 파라미터로 전달하면서, 호출되는 함수에서 해당 객체를 변경한 예이다.

public void Run()
{
    DataSet ds = new DataSet();
    AddTable(ds);
    Console.WriteLine(ds.Tables.Count); // 1
}

public void AddTable(DataSet ds)
{
    DataTable dt = new DataTable("Table1");
    dt.Columns.Add("ColA", typeof(string));
    ds.Tables.Add(dt);
}

그러면 레퍼런스 타입 객체를 파라미터로 전달하면서 ref 를 사용하는 경우는 어떤 경우인가? ref를 사용하지 않는 레퍼런스 객체 파라미터는 해당 객체의 내부 멤버를 변경할 수는 있지만, 다른 새로운 레퍼런스 객체를 해당 파라미터에 할당할 수는 없다. 만약 아래와 같이 DataSet 파라미터를 전달하면서 이 파라미터에 새로운 DataSet 객체를 할당한다면, 아무 에러 없이 실행은 되겠지만, 호출 함수 Run()에서는 변수 ds가 호출이전의 ds를 그대로 유지하게 된다. 따라서 출력은 1이 아닌 0이 된다.

public void Run()
{
    DataSet ds = new DataSet();
    AddTable(ds);
    Console.WriteLine(ds.Tables.Count); // 0
}

public void AddTable(DataSet ds)
{
    DataSet newDs = new DataSet();
    DataTable dt = new DataTable("Table1");
    dt.Columns.Add("ColA", typeof(string));
    newDs.Tables.Add(dt);

    ds = newDs;
}

위의 오류를 해결하기 위해서는 AddTable(ref DataSet ds)와 같이 ref를 추가한다.



본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.