본문 바로가기

개인공부/C#

[C#] Call by Value, Call by Reference

 

Method 호출 방식에는 Call by value, Call by reference가 있음

 

■ Call by Value : 값에 의한 호출

- 값에 의한 호출이기 때문에 x, y에 a, b의 값이 할당

- x, y를 수정해도 a, b는 영향 없음

■ Example

static unsafe void Main(string[] args)
{
    int a = 100;
    int b = 200;

    Console.WriteLine($"[Main] a Addr = {(long)&a:X}, b Addr = {(long)&b:X}");
    Console.WriteLine($"[Main] a Value = {a}, b Value = {b}");
    Console.WriteLine();
    CallByValue(a, b);
    Console.WriteLine($"[Main] a Value = {a}, b Value = {b}");
}

static unsafe void CallByValue(int x, int y)
{
    Console.WriteLine($"[CallByValue] x addr = {(long)&x:X}, y addr = {(long)&y:X}");
    Console.WriteLine($"[CallByValue] x value = {x}, y value = {y}");
    Console.WriteLine($"[CallByValue] x,y value Change");
    Console.WriteLine();
    x = 300;
    y = 400;
    Console.WriteLine($"[CallByValue] x value = {x}, y value = {y}");
    Console.WriteLine();
}

 

a, x와 b, y의 메모리 주소 불일치

 - Main에서 변수 a = 100, b = 200 초기화

 - CallByValue 메서드를 호출하여 a, b를 매개변수로 전달

 - 매개변수로 전달된 a, b는 CallByValue 메서드의 x, y에 할당

 - x = 300, y = 400으로 수정

 - CallByValue 내에서 변수 x, y 출력, 정상적으로 수정된 것 확인

 - CallByValue  메서드 종료

 - Main에서 변수 a, b 출력, 수정되지 않음

 

■ Call by Reference : 참조에 의한 호출

 - 참조에 의한 호출이기 때문에 x, y에 a, b의 메모리 주소가 할당

 - x, y는 a, b를 참조하고 있기 때문에 x, y의 수정은 a, b의 수정

 - ref 키워드 사용

■ Example

static unsafe void Main(string[] args)
{
    int a = 100;
    int b = 200;

    Console.WriteLine($"[Main] a Addr = {(long)&a:X}, b Addr = {(long)&b:X}");
    Console.WriteLine($"[Main] a Value = {a}, b Value = {b}");
    Console.WriteLine();
    CallByReference(ref a, ref b);
    Console.WriteLine($"[Main] a Value = {a}, b Value = {b}");
}

static unsafe void CallByReference(ref int x, ref int y)
{
    long ptr_x;
    long ptr_y;
    fixed (int* px = &x) { ptr_x = (long)px; }
    fixed (int* py = &y) { ptr_y = (long)py; }
    Console.WriteLine($"[CallByReference] x addr = {(long)ptr_x:X}, y addr = {(long)ptr_y:X}");
    Console.WriteLine($"[CallByReference] x value = {x}, y value = {y}");
    Console.WriteLine($"[CallByValue] x,y value Change");
    Console.WriteLine();
    x = 300;
    y = 400;
    Console.WriteLine($"[CallByReference] x value = {x}, y value = {y}");
    Console.WriteLine();
}

 

a, x와 b, y의 메모리 주소 일치

 - Main에서 변수 a = 100, b = 200 초기화

 - CallByReference 메서드를 호출하여 a, b를 매개변수로 전달

 - 매개변수로 전달된 a, b는 CallByReference 메서드의 x, y에 할당

 - x = 300, y = 400으로 수정

 - CallByValue 내에서 변수 x, y 출력, 정상적으로 수정된 것 확인

 - CallByValue  메서드 종료

 - Main에서 변수 a, b 출력, x, y와 동일하게 수정됨

 

 

■ ref :

 - 값이 참조로 전달됨

 - 전달되기 전에 변수 초기화

ref 키워드는 초기화 되지 않은 변수를 사용하면 ERROR 발생

 

■ out :

 - 값이 참조로 전달됨

 - 전달되기 전에 초기화 필요 없음

 - 매개변수의 초기 값은 메서드 내에서 무시

 - 초기화되지 않은 것을 제외하면 ref와 유사함

out 키워드는 메서드 내에서 할당하지 않으면 ERROR 발생

■ Example

static void Main(string[] args)
{
    int a = 100;
    int b = 200;
    int c = RefMethod(ref a, ref b);
    Console.WriteLine($"[RefMethod] a : {a}, b : {b}, c : {c}");


    int A;
    int B;
    int C = OutMethod(out A, out B);
    Console.WriteLine($"[OutMethod] A : {A}, B : {B}, C : {C}");
}

static int RefMethod(ref int x, ref int y)
{
    x = 300;
    y = 400;
    return 500;
}

static int OutMethod(out int x, out int y)
{
    x = 600;
    y = 700;
    return 800;
}

 

ref, out 키워드를 사용하면 다수의 결과 값을 반환하는 구현 메서드 가능