본문 바로가기
개발일지/C#

C#) ref

by 태운콩즙 2024. 10. 1.
728x90
반응형

C# ref 키워드

  • ref 가 하는일ref 키워드를 이용하면 명시적으로 call by refence(참조 전달)을 할수있습니다정수 타입들은 기본적으로 매개변수로 보낼때 call by value값이 전달 되기 때문에
    public void ChangeNum(int num)
    {
    	num = 10;
    }
    
    int a = 99;
    ChangeNum(a);
    Console.WriteLine(a);    // a는 그대로 입니다
    
  • 전달하는 변수와의 관계가 끊어지게 된다
  • 참조 전달을 하게되면 매게변수로 전달한 값의 원본이 변경이 된다
  • 기본적으로 c# 메서드에 인자를 전달할때 call by value (값 전달)을 합니다.

a의 값 99를 전달 하더라도 ChangeNum에서 num 으로 매개변수를 받을 때 call by value 이기 때문에 문자 그대로 99만 전달이 된다

메서드 밖에 a 와 ChangeNum 내부에 있는 num은 관계가 없다

참조로 전달을 하면 해당 변수에 별칭이 생김

ref 키워드를 붙이면 call by reference가 된다

public void ChangeNum(ref int num)
{
	num = 10;
}

int a = 99;

ChangeNum(ref a);
Console.WriteLine(a);      // a는 10 입니다

이렇게 되면 변수 a 도 num도 동일한 변수를 나타내게 되고 함수 내부에서 값을 바꾸면

함수 밖에 있는 것도 영향을 주게 된다

**

참조를 전달 한 다는 것은 참조 형식과 개념이 다름

값 형식이 참조로 전달될 때 boxing 되지 않는다

그대로 전달된 매개변수에 별칭을 붙여서 해당 변수의 값을 변경하는 방식

참조 타입의 객체들 같은 경우에는 기본적으로 call by value 로 (ref 키워드를 붙이지 않고) 전달 하더라도 함수 내부에서 객체의 상태를 변경 할 수 있다 ( 함수 밖에 있는 객체에 영향을 줌)

명시적으로 전달하거나 객체 내부가 아닌 객체 자체를 변경할 수 도 있으므로 구분을 확실히 해서 ref 키워드를 붙여야함

  • ref 사용법과 특징

ref의 경우 변수를 전달하기 전에 반드시 초기화가 되어있어야 한다

ref는 함수의 매개변수 앞 부분에서도 키워드를 작성 해주어야 하며 함수 호출시에도 ref 키워드를 붙여 주어야 한다

함수 선언시 매개 변수 앞에 ref 붙여줌

public void ExFunc(ref int num) { ... };

보낼 변수 초기화 필수

int a = 10;

함수 호출시 변수 앞에 ref 붙여줌

ExFunc(ref a);

C# ref 키워드 예제

  • 값 타입 ref 비교
class MainApp
{
	public static void ChangNumRef(ref int num)
	{
		num = 10;
	}
	public static void ChangeNumVal(int num)
	{
		num = 10;
	}
	public static void Main()
	{
		//값 타입
		int a = 99;
		int b = 99;
		
		int c;  // 초기화 하지 않은 변수
		
		ChangNumVal(a);        // call by value
		ChangNumRef(ref b)     // call by refence
		// ChangNumRef(ref c); // ERROR : 초기화 하지 않은 변수는  ref로 넘길수 없습니다
		
		Console.WriteLine($"a = {a}, b = {b}")
		Console.WriteLine($"call by value 'a'     : {a}");       
    Console.WriteLine($"call by reference 'b' : {b}");
	}
}

위 예제같이 타입의 경우에는 ref 를 사용 하는 것 과 안 하는 것의 차이가 확실하다

ref를 붙이지 않는 경우에는 함수 밖에 있는 변수에 영향을 전혀 주지 않고

ref 를 붙이는 경우에 함수 밖에 있는 변수에 영향을 주게 된다

  • 참조 타입 ref 비교
using System;;

namespace test
{
	public class MyName
	{
		public int num = 10;
		public string name = "test";
		
		public void PrintAll()
		{
			Console.WriteLine($"num : {num}, name : {name}");
		}
	}
}
class MainApp
{
	public static void ChangeVal(MyName myName)
	{
		Console.WriteLine("\\nCalled 'ChangeVal'....")'
		myName.num = 111;
		myName.name = "Value Name";
	}
	
	public static void ChangeRef(ref MyName myName)
	{
		Console.WriteLine("\\nCalled 'ChangeRef"....");
		myName.num = 222;
		myName.name = "Ref Name";
	}
	
	public static void Main()
	{
		// 참조 타입
		MyName myName = new MyName();
		myName.PrintAll(); // 선언 하자마자 확인
		
		ChangeVal(myName);
		myName.PrintAll(); // ref 선언 안하고 함수 호출후 확인
		
		ChangeRef(ref myName);
		myName.PrintAll(); // ref 함수 호출 후 확인
	}
}

참조타입(class)는 ref 를 선언을 하던 하지 않던 함수 인자로 넘겨서 값을 변경하게 되면 함수 밖에 있는 것도 영향을 준다

  • 참조 타입 객체 할당 ref 비교
using System;

namespace test
{
	public class MyName
	{
		public int num;
		public string name;
		
		public void PrintAll();
		{
			Console.WriteLine($"num : {num}, name : {name}");
		}
	}
}

class MainApp
{
	public static void ChangeVal(MyName innerMyName)
	{
		Console.WriteLine("\\nCalled'ChangeVal'....");
		innerMyname = new MyName(111, "Value test"); // 새 객체 할당 
	}
	
	public static void ChangeRef(ref Myname innerMyName)
	{
		Console.WriteLine("\\nCalled 'ChangeRef'...."); // 새 객체 할당
	}
	
	public static void Main()
	{
		Myname myName = new MyName(99, "test");
		myName.PrintAll();
		
		ChangeVal(myName);
		myName.PrintAll();
		
		ChangeRef(ref myName);
		myName.PrintAll()
	}
}

새로운 객체를 생성해서 연결을 할 때 참조 타입 에서 차이가 나게 됨

728x90
반응형

'개발일지 > C#' 카테고리의 다른 글

회계 관리 프로그램 예제  (1) 2024.11.09
인사 급여 관리 프로그램 예제  (0) 2024.11.08
C# Delegate  (2) 2024.10.02
C# Indexer  (0) 2024.10.02
yield  (5) 2024.10.01