C#

C# 04( 제네릭 )

상상모음 2025. 3. 12. 16:00

제네릭(generic)

제네릭의 의미

자료형을 매개변수로 가질수있는 개념

C++의 템플릿과 유사한 개념

제네릭 단위

클래스, 구조체, 인터페이스, 메소드

제네릭 클래스

범용 클래스 또는 포괄 클래스

형 매개변수(type parameter) - <> 안에 기술한다.

제네릭이 뭐야?

제네릭(Generics)은 어떤 데이터 타입이든 사용할 수 있도록 만드는 방법!
즉, "데이터 타입을 미리 정하지 않고, 나중에 사용할 때 정할 수 있는 것"!


제네릭이 왜 필요할까?

만약 두 개의 숫자를 바꾸는 함수(Swap)를 만든다고 해보자!

void Swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}

근데 문자열(String)을 바꾸려면?

void Swap(string a, string b)
{
    string temp = a;
    a = b;
    b = temp;
}

비슷한 함수를 계속 만들어야 해서 귀찮아!

제네릭을 사용하면?

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

이제 숫자, 문자열, 실수 다 사용 가능!

int x = 10, y = 20;
Swap(ref x, ref y);
Console.WriteLine(x + ", " + y); // 결과: 20, 10

string s1 = "hello", s2 = "world";
Swap(ref s1, ref s2);
Console.WriteLine(s1 + ", " + s2); // 결과: world, hello

한 번만 만들면 여러 타입에서 사용 가능! 


제네릭 클래스 만들기!

제네릭은 클래스에서도 사용할 수 있어!

제네릭 없는 버전

class IntBox
{
    public int Value;
    public IntBox(int value)
    {
        Value = value;
    }
}

class StringBox
{
    public string Value;
    public StringBox(string value)
    {
        Value = value;
    }
}

int, string 따로 만들어야 해서 비효율적!


제네릭을 사용한 클래스!

class Box<T>
{
    public T Value;  // 어떤 타입이든 저장 가능!

    public Box(T value)
    {
        Value = value;
    }
}

이제 int, string, double 등 어떤 타입이든 사용할 수 있어!

Box<int> intBox = new Box<int>(123);
Box<string> strBox = new Box<string>("Hello");
Box<double> doubleBox = new Box<double>(3.14);

Console.WriteLine(intBox.Value);   // 결과: 123
Console.WriteLine(strBox.Value);   // 결과: Hello
Console.WriteLine(doubleBox.Value); // 결과: 3.14

제네릭을 사용하면 클래스 하나로 모든 타입을 처리 가능!


제네릭 메서드 만들기!

제네릭은 클래스뿐만 아니라, 메서드에서도 사용 가능!

제네릭 메서드 예제

class Utils
{
    public static void Print<T>(T item)
    {
        Console.WriteLine("값: " + item);
    }
}

이제 모든 타입을 출력 가능!

Utils.Print(123);     // 결과: 값: 123
Utils.Print("Hello"); // 결과: 값: Hello
Utils.Print(3.14);    // 결과: 값: 3.14

이제 타입마다 Print 함수를 따로 만들 필요가 없어!


제네릭 제약 조건(Constraints)

제네릭을 사용할 때 특정 타입만 허용하고 싶을 때가 있어!

예를 들어, Compare 함수에서 숫자 타입만 비교 가능하게 하려면?

class Utils
{
    public static bool Compare<T>(T a, T b) where T : IComparable<T>
    {
        return a.CompareTo(b) == 0;
    }
}

이제 숫자, 문자열은 비교 가능하지만, 비교할 수 없는 타입은 사용 불가능!

Console.WriteLine(Utils.Compare(10, 10));   // 결과: True
Console.WriteLine(Utils.Compare("A", "B")); // 결과: False
// Console.WriteLine(Utils.Compare(new Object(), new Object())); // 오류 발생!

제약 조건을 사용하면, 불필요한 사용을 막을 수 있어!


정리!

C# 제네릭(Generics) 핵심 정리!

  1. 제네릭(Generics)이란?
     데이터 타입을 미리 정하지 않고, 사용할 때 정하는 기능!
  2. 제네릭 클래스 모든 타입을 저장할 수 있는 박스를 만들 수 있어!
  3. class Box<T> { public T Value; }
  4. 제네릭 메서드  어떤 타입이든 출력 가능!
  5. void Print<T>(T item) { Console.WriteLine(item); }
  6. 제네릭 제약 조건 특정 타입만 허용 가능!
  7. where T : IComparable<T>

제네릭을 사용하면 코드가 짧아지고, 재사용성이 높아짐