Chapter 2-2. 코드의 흐름 제어 : 함수, ref, out

Date:     Updated:

카테고리:

태그:

인프런에 있는 Rookiss님의 강의 Part1: C# 기초 프로그래밍 입문 를 듣고 정리한 필기입니다. 😀

👱‍♀️ 함수

Call by Value

  • Call by Value 👉 a의 값을 매개변수 AddOne 함수 중괄호 안에서만 수명을 가지는 number에 넘겨준다. 즉, a값을 복사하여 number에게 넘겨준 것 뿐이라 number값이 변해도 a 값에는 전혀 변화가 없다. 따라서 0 이 출력된다. numbera와 동일한 값을 가진 것 뿐인 별개의 메모리를 가진다.
      class Program
      {
          static void AddOne(int number)
          {
              number = number + 1;
          }
          static void Main(string[] args)
          {
              int a = 0;
              Program.AddOne(a);
              Console.WriteLine(a); // 0 출력 
          }
      }
    

Call by Reference

  • Call by Reference 👉 a의 값이 아닌 a 메모리 자체를 AddOne 함수 중괄호 안에서만 수명을 가지는 number공유한다. 따라서 number 값이 변하면 a 값도 변한다. 그래서 a를 출력하면 1이 출력될 것이다. 둘은 동일한 메모리를 참조한다.
      class Program
      {
          static void AddOne(ref int number)
          {
              number = number + 1;
          }
          static void Main(string[] args)
          {
              int a = 0;
              Program.AddOne(ref a);
              Console.WriteLine(a); // 1 출력
          }
      }
    
    class Program
    {
        static void AddOne(ref int number)
        {
            number = number + 1;
        }

        static int AddOne2(int number)
        {
            return number + 1;
        }

        static void Main(string[] args)
        {
            int a = 0;

            Program.AddOne(ref a);
            a = Program.AddOne2(a);

            Console.WriteLine(a); // 2 출력 
        }
    }
Program.AddOne(ref a);

1️⃣ 이 방법은 원본 a를 바꿀 수 있는 특성을 가진다. 사본 생성 과정이 없는 것은 효율적이지만 원본을 꼭 변경시킨다는 점도 있다. 따라서 경우에 따라 효율성이 결정될 것이다.

a = Program.AddOne2(a);

2️⃣ 디자인 상으론 이 방법이 더 좋다. 원본 a를 바꾸지 않으면서 b = Program.AddOne2(a) 이렇게 다른 변수에도 리턴시킬 수도 있다. 단 입력 크기가 아주아주 커서 사본 생성에 부담이 따를 때엔 이 방법은 좋지 않을 듯 하다.


디폴트 매개 변수 in C#

    class Program
    {
        static int Add(int a, int b, int c = 0, float d = 1.0f, double e = 3.0)
        {
            return a + b + c;
        }

        static void Main(string[] args)
        {
            Program.Add(1, 2, d:2.0f);
        }
    }
  • 매개 변수 c, d, e 는 인수를 넘기지 않더라도 각각의 디폴트 값으로 설정된다.
  • C++ 에선 인수를 넘길 때 꼭 매개 변수와 대응되게 자리를 맞춰주어야 했지만 C# 에선 위와 같이 d 매개변수에 대해선 인수를 따로 넘겨주고 싶다면 d:2.0f와 같이 넘길 수 있다.


👱‍♀️ ref & out

ref

refCall by Reference 로 받기 위한 키워드다.

  • 자료형 보다도 앞에 쓰인다. ref int a
  • 매개 변수는 & 타입이라도 인수에까지 &을 붙일 필요는 없었던 C++ 문법과는 다르게 C# 에선 넘겨주는 ✔인수까지 꼭 ref를 붙여주어야 한다. 매개 변수가 ref int number로 선언되어 있다면 인수도 마찬가지로 꼭 ref a로 넘겨주어야 한다.
    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;

            Program.Swap(ref num1, ref num2);

            Console.WriteLine(num1); // 2 출력
            Console.WriteLine(num2); // 1 출력
        }
    }


out

ref라는 똑같다. Call by Reference. 매개 변수에 저장을 강제하는 ref라고 생각하면 된다.

  • 매개 변수가 ref인 경우
    • 매개 변수에 값을 저장(write)하지 않고 그저 읽기(read)만 하더라도 문법적 오류 전혀 없다.
      • 즉 매개변수를 call by reference 로 인수의 메모리를 참조하기로 해놓고는 아무런 사용도 안해도 문제가 전혀 없다.
    • [함수 외부] <-> [함수 내부] 양방향으로 통신하기 위해서 데이터 참조를 주고 받기 위한 개념
      • 읽기 + 쓰기 가능. 사용하지 않아도 됨.
    • 함수 내부/외부 사이에 데이터를 빠르게 넘겨주기 위해 사용.
    • 반드시 초기화가 되어 있는, 메모리가 비어 있지 않은 변수에만 ref를 사용할 수 있다. 초기화 되지 않은 변수에 ref 붙이며 컴파일 오류가 난다. 함수 내부에서 그냥 읽기만 할 수도 있기 때문에 런타임 에러의 위험이 생길 수 있음.
  • 매개 변수가 out인 경우
    • 매개 변수에 어떤 값을 저장(write)하는 활동이 전혀 없다면 컴파일 오류를 발생시킨다. 반드시 참조 매개변수를 함수 내부에서 write 시켜야 한다. 단순 읽기만 해서는 안된다.
    • call by reference 매개 변수가 참조 중인 메모리의 사용을 강제하기 때문에 ref와 달리 초기화를 전혀 하지 않은 변수를 인수로서 out 매개 변수에 넘기는 것이 가능하다.
      • 함수가 끝나면 넘겨준 인수에도 Call by Reference를 통해 어떤 값이 반드시 저장될 것이라는게 보장되기 때문이다. out이 이를 강제해서 !
    • [함수 내부]에서 작업한 최종 결과물을 [함수 외부] 쪽으로 넘겨주는 일방적 통행 (out 이름 답게!)
      • 함수 내부에서 값을 바꿔서 외부에 전달. 참조 중인 외부 메모리에도 영향을 끼침.
      • 반드시 쓰기 과정이 필요
    • 함수 내에서의 로직으로 매개 변수 write을 진행한 최종 데이터를 함수 외부로 넘겨주기 위한 용도로 사용.

image

이렇게 out이 붙은 매개 변수에 아무런 값도 저장하지 않는다면 이렇게 컴파일 오류가 뜬다. out 매개변수에 저장을 강제함! ref였으면 아무런 문제가 없다. 아래와 같이 out 매개 변수에 값을 저장하면 오류가 사라진다.

    class Program
    {
        static void Divide(int a, int b, out int result, out int result2)
        {
            result = a / b;
            result2 = a % b;
        }

        static void Main(string[] args)
        {
            int num1 = 10;
            int num2 = 3;

            Program.Divide(10, 3, out num1, out num2);

            Console.WriteLine(num1); // 3 출력
            Console.WriteLine(num2); // 1 출력
        }
    }

ref와 마찬가지로 인수에도 모두 out을 붙여주어야 한다.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

C Sharp 카테고리 내 다른 글 보러가기

댓글 남기기