Menu
Coddy logo textTech

제네릭 (클래스 및 메서드)

Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 42번째.

제네릭(Generics)을 사용하면 타입 안정성을 유지하면서 모든 데이터 타입과 함께 작동하는 클래스와 메서드를 작성할 수 있습니다. IntList, StringList, 및 DoubleList를 위해 별도의 클래스를 작성하는 대신, 이 모든 것을 처리하는 하나의 제네릭 클래스를 작성합니다.

제네릭 클래스는 일반적으로 꺾쇠괄호로 감싸인 T와 같은 타입 매개변수를 사용합니다:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

// 다양한 타입과 함께 사용
Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

Box<int>를 생성할 때, 컴파일러는 모든 Tint로 바꿉니다. 이는 컴파일 타임 타입 체크를 제공하므로, int 박스에 실수로 문자열을 저장할 수 없습니다.

제네릭 메서드도 비슷하게 작동하여, 단일 메서드가 다양한 타입에 대해 동작할 수 있도록 합니다:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // x=2, y=1

컴파일러는 인수를 통해 타입을 유추하므로, Swap<int>를 명시적으로 작성할 필요가 없습니다. 제네릭은 List<T>Dictionary<TKey, TValue>와 같은 컬렉션의 기초이며, 재사용 가능하고 타입 안전한 코드를 가능하게 합니다.

challenge icon

챌린지

쉬움

어떤 타입의 아이템이든 보관하고 관리할 수 있는 제네릭 Storage<T> 시스템을 만들어 봅시다. 한 번 작성하면 정수, 문자열 또는 다른 모든 타입과 함께 사용할 수 있는 제네릭의 강력함을 보여주는 재사용 가능한 컨테이너 클래스를 만들게 됩니다!

코드는 두 개의 파일로 구성됩니다:

  • Storage.cs: DataStorage 네임스페이스 안에 제네릭 Storage<T> 클래스를 생성합니다. 저장 컨테이너는 다음을 포함해야 합니다:
    • 아이템을 보관할 T 타입의 프라이빗 배열과 저장된 아이템 수를 추적하는 Count 속성
    • 내부 배열을 초기화하기 위해 생성자에서 용량(capacity)을 인자로 받음
    • 공간이 있는 경우 아이템을 추가하는 Add(T item) 메서드
    • 지정된 인덱스의 아이템을 반환하는 Get(int index) 메서드
    • 모든 저장된 아이템을 ", "로 연결하여 반환하는 GetAll() 메서드
  • Program.cs: 메인 파일에서 두 가지 다른 타입으로 작동하는 제네릭 클래스를 시연합니다. Storage<int>Storage<string>을 생성하고, 각각에 아이템을 추가하여 동일한 클래스가 두 타입 모두에서 원활하게 작동함을 보여주세요.

네 개의 입력을 받게 됩니다:

  • 저장할 첫 번째 정수
  • 저장할 두 번째 정수
  • 저장할 첫 번째 문자열
  • 저장할 두 번째 문자열

용량이 5인 정수 저장소와 용량이 5인 문자열 저장소를 생성하세요. 두 정수를 정수 저장소에 추가하고, 두 문자열을 문자열 저장소에 추가합니다.

출력은 다음 형식을 따릅니다:

Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}

예를 들어, 입력이 42, 100, Hello, World인 경우 출력은 다음과 같아야 합니다:

Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello

Storage<T> 클래스를 한 번만 작성했지만 intstring 모두에서 완벽하게 작동하는 방식에 주목하세요. 이것이 바로 제네릭의 마법입니다! 컴파일러가 타입 안정성을 보장하므로 정수 저장소에 실수로 문자열을 추가할 수 없습니다.

치트 시트

제네릭(Generics)을 사용하면 타입 안정성을 유지하면서 모든 데이터 타입과 함께 작동하는 클래스와 메서드를 작성할 수 있습니다.

제네릭 클래스는 꺾쇠괄호로 묶인 타입 매개변수(일반적으로 T)를 사용합니다:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

인스턴스를 생성할 때 T를 대체할 타입을 지정합니다:

Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

제네릭 메서드를 사용하면 단일 메서드가 서로 다른 타입에 대해 작동할 수 있습니다:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // // 컴파일러가 인수를 통해 타입을 추론합니다.

제네릭은 컴파일 타임 타입 체크를 제공하며 List<T>Dictionary<TKey, TValue>와 같은 컬렉션의 기초가 됩니다.

직접 해보기

using System;
using DataStorage;

class Program
{
    public static void Main(string[] args)
    {
        // 입력 읽기
        int num1 = Convert.ToInt32(Console.ReadLine());
        int num2 = Convert.ToInt32(Console.ReadLine());
        string str1 = Console.ReadLine();
        string str2 = Console.ReadLine();

        // TODO: 용량이 5인 Storage<int> 생성
        
        // TODO: 정수 저장소에 두 정수 추가
        
        // TODO: 용량이 5인 Storage<string> 생성
        
        // TODO: 문자열 저장소에 두 문자열 추가
        
        // TODO: 요구된 형식으로 출력 인쇄
        // Int storage: {GetAll()}
        // Int count: {Count}
        // First int: {Get(0)}
        // String storage: {GetAll()}
        // String count: {Count}
        // First string: {Get(0)}
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨