본문 바로가기
C#

[C#] 제네릭(Generic) 클래스

by RucA 2024. 4. 24.
728x90
반응형

System.Collections 네임스페이스에 있는 클래스들은 몹시 유용하지만, 모든 타입의 데이터를 수용하기 위해 Object형으로 데이터를 저장하기에 연산을 위해서 형변환을 하거나 타입 체크를 하기 번거롭고, 속도 자체도 느릴수밖에 없다. 이를 개선해서 설정한 타입만을 데이터로 받는 제네릭 컬렉션 클래스가 있다. 이에 대해 간단히 정리하겠다.

 

관련 네임스페이스 : using {NAMESPACE}로 사용 자주 쓰이는 클래스
System Array
System.Collections Stack, Queue, ArrayList, Hashtable
System.Collections.Generic Stack<T>, Queue<T>, List<T>, Dictionary<T>

 

 

Stack<T> 제네릭 클래스


  • 필요한 네임스페이스를 선언하고, 제네릭 클래스의 인스턴스를 생성한 후 메소드를 사용한다.
    • 지난 포스팅에서 소개한 컬렉션 Stack 클래스의 사용법에서 <타입>만 추가한 형태이다.
using System.Collections.Generic;

class GenericPractice
{
    static void Main()
    {
        Stack<string> stack = new Stack<string>();
        
        stack.Push("Hello Generic");
        Console.WriteLine(stack.Pop());
    }
}
//출력 : Hello Generic

 

 

제네릭 클래스의 장점


제네릭 클래스는 컬렉션 클래스와 비교해 다음과 같은 장점을 지닌다.

 

  • 전달 시 추가적인 형변환 필요없음
using System.Collections.Generic;

class GenericPractice
{
    static void Main()
    {
        Stack<int> stack = new Stack<int>();
        stack.Push(1111);
        
        //컬렉션 Stack 클래스의 경우, int integer = (int)stack.Pop();
        //제네릭 클래스는 형변환 없이 바로 전달
        int integer = stack.Pop();
        Console.WriteLine(integer);
    }
}
//출력 : 1111

 

  • 박싱, 언박싱에 대한 비용 절감
    • 컬렉션 Stack 클래스의 경우 모든 데이터 타입을 수용하는데, 이는 모든 데이터 타입을 "Object"형으로 변환해 저장하기 때문이다. 더 정확히 말하면, 실행시간 중 메모리 내의 힙 영역에 Object 타입의 참조형 변수를 생성하고, 입력 데이터 값을 저장한 후 생성한 변수의 주소를 반환한다. 입력 데이터를 Object 타입의 참조형 변수로 저장하는 것을 "박싱", Object 타입의 참조형 변수를 원하는 데이터 형식으로 바꿔 사용하는 것을 "언박싱"이라고 한다.
    • 박싱과 언박싱은 설명에도 알 수 있듯 추가적인 작업을 요구하기 때문에 속도가 느리며 자원을 소모한다. 제네릭 클래스는 데이터 형식이 지정되어 있기 때문에 박싱과 언박싱이 필요없다.
using System.Collections;

class GenericPractice
{
    static void Main()
    {
        Stack stack = new Stack();
        
        //int형을 object형으로 박싱
        stack.Push(2222);
        
        //object형을 int형으로 언박싱
        int integer = (int)stack.Pop();
        Console.WriteLine(integer);
    }
}
//출력 : 2222

 

  • 의도치 않은 데이터 타입 입력 방지
using System.Collections.Generic;

class GenericPractice
{
    static void Main()
    {
        Stack<string> stack = new Stack<string>();
        stack.Push("1111");
        
        //에러 발생 : Error CS1503 : 1 인수: 'int'에서 'string'(으)로 변환할 수 없습니다.
        stack.Push(1111); 
    }
}

 

 

Queue<T> 제네릭 클래스


  • 필요한 네임스페이스를 선언하고, 제네릭 클래스의 인스턴스를 생성한 후 메소드를 사용한다.
    • 지난 포스팅에서 소개한 컬렉션 Queue 클래스의 사용법에서 <타입>만 추가한 형태이다.
using System.Collections.Generic;

class GenericPractice
{
    static void Main()
    {
        Queue<string> queue = new Queue<string>();
        
        queue.Enqueue("queue!!");
        Console.WriteLine(queue.Dequeue());
    }
}
//출력 : queue!!

 

 

List<T> 제네릭 클래스


  • 필요한 네임스페이스를 선언하고, 제네릭 클래스의 인스턴스를 생성한 후 메소드를 사용한다.
    • 지난 포스팅에서 소개한 컬렉션 ArrayList 클래스의 사용법에서 <타입>만 추가한 형태이다.
    • List 제네릭 클래스는 특히 많이 사용된다.
using System.Collections.Generic;

class GenericPractice
{
    static void Main()
    {
        List<string> fruits = new List<string>();
        
        fruits.Add("apple");
        fruits.Add("peach");
        fruits.Add("cherry");

        for (int i = 0; i < fruits.Count; i++)
        {
            Console.WriteLine($"{fruits[i]}");
        }
    }
}
//출력 : apple peach cherry

 

 

Dictionary<T, T> 제네릭 클래스


  • 필요한 네임스페이스를 선언하고, 제네릭 클래스의 인스턴스를 생성한 후 메소드를 사용한다.
    • 지난 포스팅에서 소개한 컬렉션 Hashtable 클래스와 유사한 구조에 <타입>을 추가했다.
    • 없는 키를 요청하면 에러가 발생하는데, 이를 확인 및 제어하기 위한 메서드도 존재한다.
using System.Collections.Generic;

class GenericPractice
{
    static void Main()
    {
        Dictionary<string, string> dic = new Dictionary<string, string>();
        
        //딕셔너리 데이터 추가
        dic.Add("C#", "fun");
        dic.Add("Python", "easy");
        dic.Add("C", "Oh..");

        //딕셔너리 데이터 삭제 : 키 기준
        dic.Remove("C");
        
        //인덱서를 이용한 데이터 추가
        dic["C"] = "awesome"

        //딕셔너리 출력
        foreach (var lang in dic)
        {
            Console.WriteLine("{0} is {1}", lang.Key, lang.Value);
        }
    }
}
//출력 : C# is fun  Python is easy  C is awesome

 

 

이상으로 자주 쓰이는 제네릭 클래스를 간단히 다뤄보았다. 더 많은 제네릭 클래스와 제네릭 메서드가 있지만, 위의 내용이 이해가 됬다면 공식 문서에서 추가로 읽고 Rider나 비주얼 스튜디오의 도움을 받아 사용하면 될 듯하다.

 

 

볼 사람을 위한 링크

https://learn.microsoft.com/ko-kr/dotnet/api/system.collections.generic?view=net-8.0

 

System.Collections.Generic 네임스페이스

제네릭 컬렉션을 정의하는 클래스와 인터페이스가 포함되어 있습니다. 이를 통해 사용자는 제네릭이 아닌 강력한 형식의 컬렉션보다 형식 안전성과 성능이 높은 강력한 형식의 컬렉션을 만들

learn.microsoft.com

https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/generics/generic-classes

 

제네릭 클래스 - C# 프로그래밍 가이드 - C#

연결된 목록, 해시 테이블, 스택, 큐, 트리와 같은 컬렉션에 사용되는 제네릭 클래스에 대해 알아봅니다.

learn.microsoft.com

 

728x90
반응형