전체 코드

namespace CSharp
{
    internal class Program
    {
        

        static void AddOne(ref int number)// 복사 
        {
            number = number + 1;
        }
        static int AddOne2(int number)
        {
            return number + 1;
        }
        // swap

        static void Swap(ref int a, ref int b)
        {
            int temp = a;
            a = b;
            b = temp;
        }
        // 반환하고 싶은 값이 여러개일 경우 사용하는 키워드
        // ref를 이용해서 값을 넣어준다. -> ref를 사용하지 않아고 컴파일러는 문제 삼지 않음
        // 
        // out
        // 
        static void Divide(int a, int b, out int result1, out int result2) // 사용하지 않으면 에러 발생
        {
            result1 = a / b;
            result2 = a % b;
        }
        static void Main(string[] args)
        {

            //int a = 0;
            //Program.AddOne(ref a);
            //Console.WriteLine(a);
            //// 디자인상 AddOne2가 더 좋다
            //// 값을 사용할 수 있는 방법이 더 많다

            //a = Program.AddOne2(a);
            //Console.WriteLine(a);

            int num1 = 1;
            int num2 = 2;
            Program.Swap(ref num1, ref num2);
            Console.WriteLine(num1);
            Console.WriteLine(num2);

            int result1;
            int result2;
            Divide(10, 3, out result1, out result2);
            Console.WriteLine(result1);
            Console.WriteLine(result2);
        }
    }
}

1. ref 키워드

개념 및 특징

  • Call by Reference 방식:

    • ref는 참조에 의한 전달(Call by Reference) 방식을 사용합니다.
    • 함수 내부에서 매개변수의 값을 읽거나 쓸 때, 해당 매개변수가 참조하는 실제 메모리에 직접 접근합니다.
  • 사용 시 주의사항:

    • 매개변수를 선언할 때 자료형 앞에 ref를 붙입니다. 예: ref int a
    • 반드시 호출 시에도 인수에 ref를 붙여줘야 합니다. (C++에서는 &를 붙이지 않아도 되지만, C#은 반드시 붙여야 함)
      • 예를 들어, 매개변수가 ref int number로 선언되었다면, 호출할 때는 ref a와 같이 사용해야 합니다.
    • 초기화 필수:
      • ref를 사용하는 인수는 반드시 미리 초기화되어 있어야 합니다.
      • 초기화되지 않은 변수에 ref를 사용하면 컴파일 오류가 발생합니다.
  • 읽기와 쓰기 모두 가능:

    • ref는 함수 내부에서 해당 변수의 값을 읽거나 쓸 수 있음
    • 매개변수가 단순히 읽기만 하더라도 문법적으로 문제 없이 사용할 수 있습니다.

예제 코드 – 값 교환(Swap) 함수

class Program
{
    static void Swap(ref int a, ref int b)
    {
        int temp = a;
        a = b;
        b = temp;
    }

    static void Main(string[] args)
    {
        int num1 = 1;
        int num2 = 2;

        // ref 키워드를 사용하여 인수 전달
        Program.Swap(ref num1, ref num2);

        Console.WriteLine(num1); // 2 출력
        Console.WriteLine(num2); // 1 출력
    }
}
  • 설명:
    • Swap 메서드는 두 정수의 값을 서로 교환합니다.
    • ref를 사용함으로써, num1과 num2의 실제 메모리가 전달되고, 함수 내부에서 변경된 값이 호출한 쪽에도 바로 반영됩니다.

2. out 키워드

개념 및 특징

  • 역할:

    • out 역시 Call by Reference 방식을 사용하지만, 주로 함수의 결과값을 반환하기 위한 목적으로 사용됩니다.
    • 함수 내부에서 반드시 매개변수에 값을 할당(write) 해야 합니다. (할당하지 않으면 컴파일 오류 발생)
  • 사용 시 주의사항:

    • 매개변수를 선언할 때 ref와 동일하게 자료형 앞에 out을 붙입니다. 예: out int result
    • 함수 호출 시에도 인수에 반드시 out을 붙여야 합니다.
    • 초기화 불필요:
      • out 매개변수로 전달되는 변수는 함수 호출 전 초기화하지 않아도 됩니다.
      • 함수 내부에서 반드시 값이 할당되므로, 함수 실행 후에는 인수에 결과값이 저장된다는 보장이 있습니다.
    • 일방적인 데이터 전달:
      • out은 함수 내부에서 계산한 값을 함수 외부로 전달하는 데 주로 사용됩니다.
      • 함수 내부에서는 반드시 쓰기(write) 작업을 통해 값을 할당해야 합니다.

예제 코드 – 나눗셈 함수

class Program
{
    static void Divide(int a, int b, out int result1, out int result2)
    {
        result1 = a / b;  // 몫을 result1에 저장
        result2 = a % b;  // 나머지를 result2에 저장
    }

    static void Main(string[] args)
    {
        int num1, num2; // 초기화하지 않아도 됨

        // out 키워드를 사용하여 인수 전달
        Program.Divide(10, 3, out num1, out num2);

        Console.WriteLine(num1); // 3 출력
        Console.WriteLine(num2); // 1 출력
    }
}
  • 설명:
    • Divide 메서드는 두 정수를 나눈 몫과 나머지를 out 매개변수에 저장합니다.
    • 함수 호출 시, num1과 num2는 초기화하지 않아도 되며, 함수 내부에서 할당한 값이 호출한 쪽으로 전달됩니다.

3. ref와 out의 비교

구분refout
초기화 여부반드시 초기화된 변수를 전달해야 함초기화되지 않은 변수도 전달 가능
용도읽기/쓰기가 모두 필요한 경우함수 내부에서 반드시 값 할당 후 결과 전달 시 사용
값 사용함수 내부에서 값 읽기와 쓰기 모두 가능함수 내부에서 반드시 값 쓰기가 필요
호출 시인수에도 반드시 ref를 붙여야 함인수에도 반드시 out을 붙여야 함
  • ref:

    • 양방향 통신에 적합합니다.
    • 함수 내부에서 인수의 값을 읽거나 수정할 때 모두 사용 가능합니다.
  • out:

    • 결과를 반환하기 위한 일방적 통신에 적합합니다.
    • 함수 내부에서 반드시 값을 할당해야 하며, 주로 여러 개의 결과를 반환할 때 사용됩니다.

profile
李家네_공부방

0개의 댓글