공부/C#

[C#] 출력 전용 매개변수 (ref, out)

코멍이 2023. 8. 8. 17:41

 

메소드를 이용하여 간단한 계산기를 만들어보았다.

매개변수를 통해 전달받은 두 값을 각각 더하고, 빼고, 곱하고, 나눈 값을 반환할 것이다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_Project
{
    class RefOut
    {
        static int Calculator(int a, int b)
        {
            int add = a + b;
            return add;
        }

        static void Main(string[] args)
        {
            int x = 10;
            int y = 5;

            Console.WriteLine(x + "+" + y+"= "+Calculator(x,y));
        }
    }

    
}

 

a와 b의 합을 구하는 코드는 무사히 작성하였다.

이제 남은건 뺄셈과 곱셈, 그리고 나눗셈의 몫이다.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_Project
{
    class RefOut
    {
        static int Calculator(int a, int b)
        {
            int add = a + b;
            int subtract = a - b;
            int multiply = a * b;
            int divid = a / b;

            return add;
        }

        static void Main(string[] args)
        {
            int x = 10;
            int y = 5;

            Console.WriteLine(x + "+" + y+"= "+Calculator(x,y));
        }
    }
    
}

 

남은 계산 부분도 마저 구현해주었다.

 

그런데 한 가지 문제가 생겼다.

계산을 하기는 했는데 값을 반환하질 못 하고 있다. 

 

이처럼 두 개 이상의 결과값을 반환해야 하는 메소드는 어떻게 구현해야 할까?

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_Project
{
    class RefOut
    {
        static void Calculator(int a, int b,ref int add, 
        ref int subtract, ref int multiply, ref int divide)
        {
            add = a + b;
            subtract = a - b;
            multiply = a * b;
            divide = a / b;
        }

        static void Main(string[] args)
        {
            int x = 10;
            int y = 5;

            int a = 0;
            int b = 0;
            int c = 0;
            int d = 0;

            Calculator(x, y, ref a, ref b, ref c, ref d);

            Console.WriteLine(x + "+" + y+"= "+a);
            Console.WriteLine(x + "-" + y + "= " + b);
            Console.WriteLine(x + "x" + y + "= " + c);
            Console.WriteLine(x + "/" + y + "= " + d);
        }
    }   
}

 

참조에 의한 매개전달 방식을 사용하면 된다. (ref 키워드)

ref 키워드가 붙은 매개변수는 원본 변수(또는 상수)를 직접 참조하며 같은 공간을 공유한다.

 

따라서 메소드 내에서 계산을 진행한 후, 결과값을 ref 키워드가 붙은 매개변수에 할당하여주면 원본 변수의 값 또한 변화하게 된다.

 

 

 

 

<실행 결과>

 

 

 

 

ref 키워드 대신 out 이라는 키워드를 사용할 수도 있다.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_Project
{
    class RefOut
    {
        static void Calculator(int a, int b,out int add, 
        out int subtract, out int multiply, out int divide)
        {
            add = a + b;
            subtract = a - b;
            multiply = a * b;
            divide = a / b;
        }

        static void Main(string[] args)
        {
            int x = 10;
            int y = 5;

            int a = 0;
            int b = 0;
            int c = 0;
            int d = 0;

            Calculator(x, y, out a, out b, out c, out d);

            Console.WriteLine(x + "+" + y+"= "+a);
            Console.WriteLine(x + "-" + y + "= " + b);
            Console.WriteLine(x + "x" + y + "= " + c);
            Console.WriteLine(x + "/" + y + "= " + d);
        }
    }
  
}

 

사용 방법은 ref와 동일하다. ref에서 out으로 키워드를 바꿔주기만 하면 된다.

결과 역시 ref를 사용했을때와 똑같이 나온다. 

 

 

 

그렇다면 ref와 out의 차이점은 무엇이고 어느 상황에서 어떤 키워드를 사용하는것이 적절할까?

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Csharp_Project
{
    class RefOut
    {
        static void Calculator(int a, int b,out int add, out int subtract, 
        out int multiply, out int divide)
        {
            add = a + b;
            subtract = a - b;
            multiply = a * b;
            divide = a / b;
        }

        static void Main(string[] args)
        {
            int x = 10;
            int y = 5;

            Calculator(x, y, out int a, out int b, out int c, out int d);

            Console.WriteLine(x + "+" + y+"= "+a);
            Console.WriteLine(x + "-" + y + "= " + b);
            Console.WriteLine(x + "x" + y + "= " + c);
            Console.WriteLine(x + "/" + y + "= " + d);
        }
    }
   
}

 

 

ref와 out의 차이를 알아보기 위해 코드를 약간 수정하였다.

out 키워드는 소드를 호출하는 쪽에서 초기화 하지 않은 변수를 사용하여도 매개변수를 넘길 수 있다.

ref를 사용하였을때는 모두 0으로 초기화를 해주었는데 코드가 훨씬 간략해졌다.

 

(ref 키워드를 사용할때 초기화 하지 않은 변수를 매개변수로 넘기면 컴파일 에러가 발생한다.)

 

 

실제 경험한 무수한 오류의 향연...

 

또한, out 키워드를 사용하면 메소드가 해당 매개변수에 아무런 결과도 할당하지 않았을때 컴파일러는 오류 메시지를 출력한다.

 

 

add=a+b 코드를 주석처리 하자 생긴 컴파일 에러이다. 

add에 아무런 값도 할당되지 않았기에 생긴 오류이다.

 

 

하지만 ref 키워드를 사용하면 동일한 경우에 오류 메시지를 출력하지 않는다.

컴파일러 오류가 생기지 않는다는 것이다.

 

 

컴파일러 오류는 없지만 완전히 잘못된 실행결과가 나온 모습.

 

대신 이러한 논리적인 오류가 생기기 쉽다.

out 키워드는 컴파일러를 통해 결과를 할당하지 않는 버그가 만들어질 가능성을 방지할 수 있다.

 

 

 

그렇다면 ref와 out 키워드는 각각 어느때에 사용하는 것이 좋을까?

 

 

ref 키워드는 앞선 게시글의 Swap 메소드 처럼 원본 변수(또는 상수)를 메소드에서 수정할때 사용하면 좋다.

(초기화 하지 않은 변수는 매개변수로 넘길 수 없음.)

 

out 키워드는 이번 게시글의 예제처럼 메소드 내에서 생성된 값을 반환할때 사용하는 것이 좋다.

(메소드 내에서 값을 저장하지 않으면 오류 메시지 출력, 초기화 하지 않은 변수를 매개변수로 넘길 수 있음.)