공부/C#

[C#] out과 ref / stack과 queue / Hashtable과 Dictionary

굴러다니다니 2023. 3. 27. 15:25
728x90

Out / ref (modifier)

C#에서 기본 데이터 형식 매개변수는 call by value, value로 값 전달이 기본이다.
이를 reference 형식으로 바꾸고 싶다면 ref / out 키워드를 사용한다.

value와 reference의 차이를 예시를 들어 설명하자면

static void example(int a){
	a = 3;
}

위의 코드는 기존의 존재한 int a를 받아 3으로 바꾸는 코드이다.

하지만 void로 설정되어있어 이를 return으로 받지 않는 한 C#은 value형식이기 때문에 a는 3으로 바뀐걸 전달해주지 못한다.

만일 return을 쓰지 않고도 값을 바꾸고 싶다면 reference 형식으로 바꿔야 한다.

 

static void example1(ref int a){
	a = 3;
}

위의 식에 ref라는 키워드를 붙여줌으로써 a는 불려와서 3으로 값이 바뀔 수 있게 되었다.

공통점: 참조를 통해 인수를 전달한다.

이렇게 참조형식으로 가능하게 하는 키워드로 ref 와 out이 있는데 무슨 차이일까?

바로 초기화에 차이점이 존재한다.

 

ref: 변수를 전달하기 전에 초기화를 해야한다. (주로 기존 변수를 메서드에서 수정할 때 사용)

out: 초기화 할 필요가 없고, 이전의 값은 무시된다. + out은 메서드를 진행하는 동안에 할당되어야 한다. (주로 메서드 내에서 생성된 값을 반환할 때 사용)

매개변수 사용하려면 method 정의와 호출 method가 모두 명시적으로 ref / out 키워드를 사용해야 한다.

한 함수에서 여러 번 ref와 out을 사용할 수 있다.

우리는 위의 상황이나 주로 여러 상황에서 ref를 주로 사용할 것이다.


Stack / Queue

스택과 큐 모두 줄세우기 / 배열과 비슷한 개념이지만, 모두 안쪽의 인덱스에는 직접 접근할 수 없다.

Stack은 동전을 쌓아 먼저 쌓은 동전이 제일 마지막에 뺄 수 있는 개념과 비슷하고, Queue는 줄을 서서 먼저 줄 선 사람은 먼저 들어갈 수 있는 개념과 비슷하다.

Stack : 후입선출, list / array같이 인덱스에 접근할 수 없다 (나가는 애들이 정해져있다)

    ex) Ctrl + Z, 동전쌓기

Queue : 선입선출

    ex) 대기번호

class Index
    {
        public int Number { get; set; }
        public Index (int number)
        {
            Number = number;
        }
    }

시작하기 전, Index 클래스를 선언해 number를 받으면 이를 Number에 저장하게 선언해두었다.

        static void first()
        {
            Stack<Index> stack = new Stack<Index>();
            for (int i = 0; i < 5; i++)
            {
                stack.Push(new Index(i));
            }
            int stack_count = stack.Count;
            for (int i = 0; i < stack_count; i++)
            {
                Index index = stack.Pop();
                Console.WriteLine(index.Number);
            }
            //4 3 2 1 0

first라는 메소드에 stack 초기화 및 0~4까지 push를 해두었다.

이를 다시 pop해서 뺀 다음 출력한다면 넣은 순서의 반대로 나오는 것을 확인할 수 있다.

 

스택 선언

   Stack<자료형> 스택이름 = new Stack<자료형>();

stack에 추가 및 삭제

   스택이름.Push(넣을 내용);

   스택이름.Pop(); -> 가장 마지막에 넣은 내용이 나온다.

            Queue<Index> queue = new Queue<Index>();
            for (int i = 0; i < 5; i++)
            {
                queue.Enqueue(new Index(i));
            }
            int queue_count = queue.Count;
            for (int i = 0; i < queue_count; i++)
            {
                Index index = queue.Dequeue();
                Console.WriteLine(index.Number);
            }

            // 0 1 2 3 4  queue[index] 접근이 
            queue_count = queue.Count;
            stack_count = stack.Count;
            Console.WriteLine("{0}, {1}", queue_count, stack_count); //0, 0찍힌다 다 꺼낸 후 queue_count는 0
        }

큐 선언

   Queue<자료형> 큐이름 = new Queue<자료형>();

큐에 추가 및 삭제

   큐이름.Enqueue(내용);

   큐이름.Dequeue();  -> 선입선출로 반환된다


Hashtable / Dictionary

Hashtable과 Dictionary는 두가지 값을 묶어서 저장하고 접근하는 형태이다.

value를 저장하며 이를 key로 접근하는 형태이다.

index로 접근하는 배열과 리스트와는 다른 형태이다.

 

Hashtable : type 정하지 않고 사용한다 (object 형태를 사용해 → 박싱 언박싱이 일어나 많이 사용하면 느려진다는 단점이 있다) 주로 자료형을 모를 때나 key값이 중복이 되는 경우에 사용한다

Dictionary : type 정하고 사용하며, key값이 중복이 되면 안된다. key값이 없을 때 빈값을 넣고, 오류를 던진다 (생성 자체가 안 됨)

 

두가지를 코드에 사용하려면 using문을 추가해야 한다.

using System.Collections;

 

            Hashtable hash = new Hashtable();
            hash.Add("a", "apple"); 
            hash.Add("b", "banana"); 
            hash.Add("c", "cat"); 
            for (int i = 0; i < hash.Count; i++)
            {
                Console.WriteLine((string)hash[i]); 
            }
            Console.WriteLine((string)hash["b"]);
            hash.Add(0, "ㅋㅋ");
            Console.WriteLine(hash[0]); //-> index 접근이 아닌 key값 0으로 접근한 것임

hashtable에서 key값에 없는 값을 넣으면 빈칸이 출력된다. -> 자료형이 정해져있지 않은 object 형식이기 때문에 (for문의 결과로 빈칸만 나온다)

string hash["b"]의 결과로 banana가 출력되며, key를 0을 가지는 value를 추가해 접근하면 이는 index로 접근하는것 처럼 보일 수 있으나, key값으로 접근한 것을 잊지말자

       

    Dictionary<int, string> dictionary = new Dictionary<int, string>();
            dictionary.Add(1, "일");
            dictionary.Add(2, "이");
            dictionary.Add(3, "삼");
            for (int i = 0; i < dictionary.Count; i++)
            {
                Console.WriteLine(dictionary[i+1]);
            }
            //Console.WriteLine(dictionary[6]); -> dictionary는 object로 받지 않아 키가 없으면 출력 안함

hashtable과 다르게 key에 없는 값을 출력하려고 하면 오류가 나며 코드가 종료된다.

선언할 때 int, string으로 key와 value의 타입을 지정한 부분을 기억해야 한다.

728x90