제네릭(Generic)은 C#에서 제공하는 강력한 기능중 하나로 코드의 재사용성과 유연성을 향상 시켜줄수 있는 수단이다.

데이터 형식을 일반화 하여 재사용 가능한 코드를 작성할 수 있도록 도움을 준다.

즉, 다양한 형식의 데이터를 처리하는 메서드와 클래스를 작성할 수 있도록 컴파일 시점에 안정성을 보장해 준다.

제네릭이 사용되는 예시

사용법 예시

public T GetMaxValue<T>(T a, T b) where T : ICompareable<T>
{
	if(a.CompareTo(b) > 0)
	{
		return a;
	}
	else
	{
		return b;
	}
}

int maxInt = GetMaxValue<int>(5,10);
string maxString = GetMaxValue<string>("hello", "world");

// 결과로 아래와 같이 출력 된다.
// 10
// world 

예시 코드를 보면 “GetMaxValue”라는 제네릭 메서드를 선언하고 사용하고 있다.

이 메서드는 두 개의 인자 ‘a’와 ‘b’를 비교하여 더 큰 값을 반환하는 기능을 가진다.

제네릭 타입의 매개변수 T는 메서드 호출 시에 실제 데이터 형식으로 대체되며, a,b는 동일한 데이터 형식이어야 한다.

제네릭 제약 조건

제네릭의 제약 조건은 제네릭 타입 매개변수(위 코드에서 T)에 적용되는 제한사항을 정의 하는 것이다.

이 조건을 통해 특정 인터페이스를 통해 구현하도록 강제하거나, 특정 클래스로 부터 상속받도록 요구 할 수 있다.

public class MyClass<T> where T : 제약조건
{
 // 클래스 
}

public void MyMethod<T>(T param) where T : 제약조건
{
	// 메서드
}

제약 조건은 다음과 같은 유형으로 설정할 수있다.

  1. where T : 클래스명 : T는 특정 클래스 또는 해당 클래스를 상속 받은 클래스여야 한다.
  2. where T : 인터페이스명 : T는 특정 인터페이스를 상속 받아 구현한 클래스여야 한다.
  3. where T : new() : T는 매개변수가 없는 기본 생성자를 가져야 한다.
  4. where T : struct : T는 값 형식 ( 구조체 ) 여야 한다.
  5. where T : unmanaged : T는 비관리 형식이어야 한다.
  6. where T : enum : T는 열거형이어야 한다.
  7. where T : delegate : T는 대리자 형식이어야 한다.

인터페이스도 제네릭을 지원한다.

public interface IDamageable<T>
{
	void Attack(T target);
}

이런식으로 다양한 클래스들이 공통적인 동작을 수행해야 할 때 제네릭 인터페이스를 이용하면 유용하게 활용할 수 있다.