Game Tech Blog

C# - ref, out, in 한정자 본문

IT Study/C#

C# - ref, out, in 한정자

jonghow 2023. 9. 25. 23:35
반응형

참조로 전달이란?

함수의 인자로 넘길때는 여러가지 방법이 있다.

1) 값으로 전달 2) 참조로 전달

C++ 로가면, Call by value, Call by reference, Call by Pointer 이렇게 얘기하는 부분들이 있는데, 쉽게 이야기하면 넘기기 직전의 값을 복사해서 값만 넘길 것이냐, 주소까지 완전 복사해서 이 인자를 수정하면 넘겼던 주체까지 수정될 수 있게 하느냐 그 차이다.

 

C# 에서 값을 참조로 변경해서 넘기기 위해서는 out, ref 키워드를 정해서 작성해야 한다. 작성 예는 아래와 같다.

public void Test_Func(ref int a){
	a += 10;
}

static void Main(){	
    int test_A = 10;
    Test_Func(ref test_A);
}

호출하는 부분에서도 변수명 앞에 ref 키워드를 붙여서 명시적으로 넘겨주어야 참조 형태로 주소까지 인자로 같이 넘긴다.

 

MSDN 에서는 다음과 같은 문법은 아래와 같은 사용 방식을 제시했다.

ref, out 키워드 차이로는 메소드 오버로딩을 할 수 없지만, ref 키워드와 키워드 자체를 붙이지 않은 경우는 메소드 오버로딩을 허용했다. 

컴파일러 단에서, "참조를 넘기는 방식에 대한 키워드 속성을 같은것으로 판단하지만, 참조 방식과 값 방식으로 넘기는 것은 서로 다른 인자전달 방식이라고 판단하여 메소드 오버로딩을 허용" 하는 것이라고 생각한다.

정확한 이유는 더 찾아봐야할 것이다.

(MSDN 내용 추가) -> ref 및 out 키워드는 서로 다른 런타임 동작을 유발하지만 컴파일 타임에는 메서드 시그니처의 일부로 간주되지 않습니다. 

즉, 컴파일 타임에선 두 키워드를 동일하게 판단하여, 메소드 오버로딩을 허용하지 않는다.

 

 

public void Test_Func(ref int i){
    i += 20;
    }
    
public void Test_Func(out int i){
    i += 20;
    }

// 컴파일 에러 발생

public void Test_Func(ref int i){
    i += 20;
    }

public void Test_Func(int i){
    i += 20;
    }
    
// 정상 메소드 오버로드 가능

 

그렇다면 왜 무슨 목적으로 키워드를 작성하는지 확인했다. 이제 서로 비슷하지만 다른 키워드인 ref, out 한정자의 차이는 무엇일까?

 

- ref 키워드

1. 호출되는 메서드에서 매개 변수로 사용되는 변수의 원본 값을 변경할 수 있다.

 

- out 키워드

1. 호출당한 메서드 내에서 생성된 값을 호출한 메서드에서 유용하게 사용할 수 있다.

2. 물론 다수의 리턴값이 필요하다면 tuple을 이용하여 다중 Return 값을 구현해도 괜찮지만, out  키워드를 이용하여 손쉽게 처리해도 된다.

 

- 결론 

ref 키워드는 사용하던 변수를 메서드내에서 가공하기 위해 원본 주소가 필요할 때 사용한다.

out 키워드는 메서드 내에서 로직을 수행하고 호출한 부분에서 결과를 가지고 사용하려할때 사용한다.

 

자, 그렇다면 In 키워드는 어떻게 사용하는 것인가?

사실 저 둘의 키워드는 상당히 비슷한 부분이 있어 같이 묶어서 설명했다.

In 키워드로 결국 참조로 인자를 넘기는 것인데, 이 키워드는 readOnly 의 속성을 가지고 있다.

이유는 값을 넘기고 호출한 부분에서 인자를 변경할 수 없다는 것이다. 고로 무조건 초기화 후 매개변수를 넘기는 것은 원칙으로 한다.

 

어떤 이유로 사용할까? 아무리 생각해도 사용이유를 잘 몰랐고, 실무에서 잘 사용해보지도 못한 키워드인데, 곰곰히 잘 생각해보면, 뭔가 핵심적인 데이터를 호출되는 메서드 내에서 필요하나, 변경되면 시스템에 문제가 있을것 같은, 그런 메서드에서 사용할 수는 있을 것 같다.

 

그러나, 사실 ref 로 가져와서 변경만 안하면 되니까... 사실 그렇게 용이한 키워드인지는 잘 모르겠다.

아래는 사용 예이다.

public void Test_Func_In(in int i){
    i = 20; // Error 
}

public void Test_Func(int i){
    i = 20;
}

public void Main(){
    int i = 10;
    
    Test_Func_In(i); // In 키워드 사용
    
    Test_Func(i); // 일반 함수 호출
}

In 키워드의 사용에는 호출하는 부분에서 In 키워드를 작성하지 않고 메서드 선언에서만 사용하면 된다.

아직 In 키워드에 대한 용이성을 찾지 못하여, 잘 사용하지는 않을것 같으나, 혹시 절대 변경되지 않은데 필요한 데이터가 있다면 한번쯤 활용해보는 것도 좋아보인다.

 

참고 

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref?redirectedfrom=MSDN 

 

ref keyword - C# Reference - C#

ref keyword - C# Reference

learn.microsoft.com

https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/t3c3bfhx(v=vs.90)?redirectedfrom=MSDN 

 

out (C# Reference)

Table of contents out (C# Reference) Article 02/15/2013 In this article --> The out keyword causes arguments to be passed by reference. This is like the ref keyword, except that ref requires that the variable be initialized before it is passed. To use an o

learn.microsoft.com

https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/keywords/in-parameter-modifier

 

in 매개 변수 한정자 - C# 참조 - C#

in 매개 변수 한정자 - C# 참조

learn.microsoft.com

반응형

'IT Study > C#' 카테고리의 다른 글

C# - 리플렉션(Reflection)  (0) 2023.09.26
C# - Partial 클래스  (0) 2022.09.27
C# - Boxing, UnBoxing  (0) 2022.04.08
C# - Enum To String ( 열거형 내용을 문자열로 변환)  (0) 2022.04.05
C# - 프로퍼티  (0) 2022.01.11
Comments