본문 바로가기
C#

[C#기초] 참조

by Meaning_ 2021. 7. 19.
728x90
반응형

 

참조


  • ref/out 키워드를 사용했다면 외부로부터 변수로만 입력받겠다는 의미를 가진다.
  • --> ref a 이런건 가능하지만 ref 10 같은건 불가능!
  • 외부로부터 저장소를 받아오겠다는 의미를 가짐.
  • ref 키워드는 함수 내부로부터 받아올 값이 있을 때 사용 
  • ref 키워드는 변수를 초기화한 후 전달해야한다.
    out=초기화 안하고 전달해도 됨,결과값을 받으려고 만든거

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 class Program
{
        static void Test1(ref int r)
        {
            r = 30;
            
        }
        static void Test2(int r)
        {
            r = 20;
            
        }
        static void Main(string[] args)
        {
            int a = 1;
            Test2(10);
            Test2(a);
            Console.WriteLine(a);
            Test1(ref a);
            Console.WriteLine(a);
 
        }
    
        
    
}
cs

 

18번째 코드의 결과는 1이고, 20번째 코드의 결과는 30이다. 분명 a의 값은 1인데 왜 이런결과가 나타나는걸까?

이유는 함수 호출 시 매개변수 값 지정하면 함수가 실행할 때 매개변수 값을 컴파일러가 사용하는 임시저장소에 저장하게 된다. 즉,Test2의 경우 저장소가 다르기 때문에 아무리 r이 20이여도 a값에 변화를 주지 않는다.

하지만 Test1의 경우 ref를 사용하였기 때문에 a가 30이 된다. r과 a가 메모리 저장소를 공유하는 것으로 봐도 무방하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 class Program
{
        static void add(int a, int b,ref int value)
        {
            value=a+b;
            
        }
          
        }
        static void Main(string[] args)
        {
            int a =20;
            int b=30;
            int ret=0;//얘가 전달됨
            add(a,b,ret);
 
 
        }
    
        
    
}
cs

이 경우, ref 키워드가 없기 때문에 20+30=0으로 값이 출력될거다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 class Program
{
        static void add(int a, int b,ref int value)
        {
            value=a+b;
            
        }
          
        }
        static void Main(string[] args)
        {
            int a =20;
            int b=30;
            int ret=0;//얘가 전달됨
            add(a,b,ref ret);
            Console.WriteLine($"{a}+{b}={ret}");
 
 
        }
    
        
    
}
cs

 

하지만 ref 키워드 사용시 20+30=50으로 출력되는 것을 확인할 수 있다.
 
여기까지 예제를 통해 알아본 내용을 정리해보자면

ref,class,out은 참조개념이고 이를 메모리 공유하는 개념으로 이해해도 된다 (아직 이해가 어려우면!) 

그렇다면 클래스 참조의 사례와 ref 활용 사례를 알아보겠다.

 

 

클래스 참조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
    {
        public int bb = 10;
    }
class program{
 static void getDevice(ref A a)
        {
            a.bb = 50;
        }
        static void Main(string[] args)
        {
            int a=1;
            A aa=new A();
            getDevice(ref aa);
            Console.WriteLine(aa.bb);
        }
    
}
cs

 

이 경우 aa의 주소값과 a 변수가 공유한다. 그래서 8번째줄 코드는 'aa의 주소값에 bb라는 변수에 50을 넣어라'를 의미한다. 

 

ref 활용

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
    {
        public int bb = 10;
    }
class program{
 static void getDevice(A a)
        {
            a = new A();
            a.bb = 20;
        }
        static void Main(string[] args)
        {
            A aa = null;
            getDevice(aa);
            Console.WriteLine(aa.bb);
        }
    
}
cs

 

이 경우 에러가 뜨는데 그 이유는 무엇일까?

 

aa의 위치 값을 getDevice의 매개변수에 전달한다. 하지만 a는 새로운 메모리 공간을 만들고, 이는 aa에서 가져온 위치값과 별개의 내용이 된다. 그러므로 오류가 난다.

 

여기에 ref 키워드를 써주면 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
    {
        public int bb = 10;
    }
class program{
 static void getDevice(ref A a)
        {
            a = new A();
            a.bb = 20;
        }
        static void Main(string[] args)
        {
            A aa = null;
            getDevice(ref aa);
            Console.WriteLine(aa.bb);
        }
    
}
cs

 

변수 a와 aa의 저장소가 공유하게 되므로 출력 값도 20이 나온다!

 

 

 

 

(추가) $ 스트링

참조 내용과는 상관 없긴 하지만, c#을 처음 배우면서 새로운 특징인 것 같아서 기록해둔다.

1
2
3
4
5
6
7
static void Main(string[] args)
 
        {
            int a = 1;
            int b = 2;
            Console.WriteLine($"a의 값은{a},b의 값은 {b}");
        }
cs

보통 printf 포멧을 쓰는데 C#에도 파이썬의 f 스트링 처럼 $ 스트링이 있다!!

 

개인적으로 f 스트링이 정말 편했는데, $스트링도 요긴하게 써먹을 것 같다!

 

 

728x90
반응형

댓글