제네릭을 사용하면 메서드, 클래스, 구조 또는 인터페이스를 정확한 데이터 형식에 맞게 조정할 수 있습니다. 예를 들어 키와 값이 Hashtable 모든 형식일 수 있도록 하는 클래스를 사용하는 대신 제네릭 클래스를 Dictionary<TKey,TValue> 사용하고 키와 값에 허용되는 형식을 지정할 수 있습니다. 제네릭의 이점 중에는 향상된 코드 재사용성 및 형식 안전성이 있습니다.
제네릭 정의 및 사용
제네릭은 저장하거나 사용하는 하나 이상의 형식에 대한 자리 표시자(형식 매개 변수)가 있는 클래스, 구조체, 인터페이스 및 메서드입니다. 제네릭 컬렉션 클래스는 형식 매개 변수를 저장하는 개체의 형식에 대한 자리 표시자로 사용할 수 있습니다. 형식 매개 변수는 해당 필드의 형식 및 해당 메서드의 매개 변수 형식으로 나타납니다. 제네릭 메서드는 해당 형식 매개 변수를 반환 값의 형식 또는 형식 매개 변수 중 하나의 형식으로 사용할 수 있습니다.
다음 코드에서는 간단한 제네릭 클래스 정의를 보여 줍니다.
public class SimpleGenericClass<T>
{
public T Field;
}
Public Class SimpleGenericClass(Of T)
Public Field As T
End Class
제네릭 클래스의 인스턴스를 만들 때 형식 매개 변수를 대체할 실제 형식을 지정합니다. 이렇게 하면 생성된 제네릭 클래스라고 하는 새 제네릭 클래스가 설정되며, 선택한 형식은 형식 매개 변수가 표시되는 모든 곳에서 대체됩니다. 결과는 다음 코드와 같이 선택한 형식에 맞게 조정된 형식 안전 클래스입니다.
public static void Main()
{
SimpleGenericClass<string> g = new SimpleGenericClass<string>();
g.Field = "A string";
//...
Console.WriteLine($"SimpleGenericClass.Field = \"{g.Field}\"");
Console.WriteLine($"SimpleGenericClass.Field.GetType() = {g.Field.GetType().FullName}");
}
Public Shared Sub Main()
Dim g As New SimpleGenericClass(Of String)
g.Field = "A string"
'...
Console.WriteLine("SimpleGenericClass.Field = ""{0}""", g.Field)
Console.WriteLine("SimpleGenericClass.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub
용어
다음 용어는 .NET에서 제네릭을 설명하는 데 사용됩니다.
제네릭 형식 정의는 템플릿으로 작동하며 포함하거나 사용할 수 있는 형식에 대한 자리 표시자를 포함하는 클래스, 구조 또는 인터페이스 선언입니다. 예를 들어 클래스에는 System.Collections.Generic.Dictionary<TKey,TValue> 키와 값의 두 가지 형식이 포함될 수 있습니다. 제네릭 형식 정의는 템플릿일 뿐이므로 제네릭 형식 정의인 클래스, 구조체 또는 인터페이스의 인스턴스를 만들 수 없습니다.
제네릭 형식 매개 변수 또는 형식 매개 변수는 제네릭 형식 또는 메서드 정의의 자리 표시자입니다. System.Collections.Generic.Dictionary<TKey,TValue> 제네릭 형식에는 키와 값의 형식을 나타내는 두 개의 형식 매개 변수
TKey
가 있습니다TValue
.생성된 제네릭 형식 또는 생성된 형식은 제네릭 형식 정의의 제네릭 형식 매개 변수에 대한 형식을 지정한 결과입니다.
제네릭 형식 인수는 제네릭 형식 매개 변수로 대체되는 모든 형식입니다.
일반 용어 제네릭 형식 에는 생성된 형식과 제네릭 형식 정의가 모두 포함됩니다.
제네릭 형식 매개 변수의 공변성 및 반공변성으로 인해 생성된 제네릭 형식을 사용할 수 있습니다. 이 제네릭 형식의 형식 인수는 대상 생성 형식보다 파생(공변성) 또는 파생(반공변성)이 적습니다. 공변성 및 반공변성(contravariance)을 통칭하여 분산이라고 합니다. 자세한 내용은 공변성 및 반공변성(contravariance)을 참조하세요.
제약 조건은 제네릭 형식 매개 변수에 대한 제한입니다. 예를 들어 형식의 인스턴스를 정렬할 수 있도록 형식 매개 변수를 제네릭 인터페이스를 구현 System.Collections.Generic.IComparer<T> 하는 형식으로 제한할 수 있습니다. 특정 기본 클래스가 있거나, 매개 변수가 없는 생성자가 있거나, 참조 형식 또는 값 형식인 형식으로 형식 매개 변수를 제한할 수도 있습니다. 제네릭 형식의 사용자는 제약 조건을 충족하지 않는 형식 인수를 대체할 수 없습니다.
제네릭 메서드 정의는 제네릭 형식 매개 변수 목록과 정식 매개 변수 목록이라는 두 개의 매개 변수 목록이 있는 메서드입니다. 형식 매개 변수는 다음 코드와 같이 반환 형식 또는 정식 매개 변수의 형식으로 표시할 수 있습니다.
T MyGenericMethod<T>(T arg) { T temp = arg; //... return temp; }
Function MyGenericMethod(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function
제네릭 메서드는 제네릭 또는 비제네릭 형식에 나타날 수 있습니다. 메서드가 제네릭 형식에 속해 있거나 바깥쪽 형식의 제네릭 매개 변수와 같은 형식을 가진 정식 매개 변수를 포함하고 있다고 해서 반드시 제네릭인 것은 아니라는 점을 유의해야 합니다. 메서드는 고유한 형식 매개 변수 목록이 있는 경우에만 제네릭입니다. 다음 코드에서는 메서드
G
만 제네릭입니다.class A { T G<T>(T arg) { T temp = arg; //... return temp; } } class MyGenericClass<T> { T M(T arg) { T temp = arg; //... return temp; } }
Class A Function G(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class Class MyGenericClass(Of T) Function M(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class
제네릭의 장점 및 단점
제네릭 컬렉션 및 대리자를 사용할 때는 다음과 같은 여러 가지 이점이 있습니다.
형식 안전성. 제네릭은 형식 안전의 부담을 컴파일러로 옮깁니다. 컴파일 시간에 적용되므로 올바른 데이터 형식을 테스트하기 위해 코드를 작성할 필요가 없습니다. 형식 캐스팅의 필요성과 런타임 오류 가능성이 줄어듭니다.
코드가 적을수록 더 쉽게 재사용할 수 있습니다. 기본 형식에서 상속하고 멤버를 재정의할 필요가 없습니다. 예를 들어 즉시 LinkedList<T> 사용할 준비가 된 것입니다. 예를 들어 다음 변수 선언을 사용하여 문자열의 연결된 목록을 만들 수 있습니다.
LinkedList<string> llist = new LinkedList<string>();
Dim llist As New LinkedList(Of String)()
성능 향상. 일반적으로 제네릭 컬렉션 형식은 값 형식을 상자에 입력할 필요가 없으므로 값 형식을 저장하고 조작하는 데 더 적합합니다.
제네릭 대리자는 여러 대리자 클래스를 만들 필요 없이 형식이 안전한 콜백을 사용하도록 설정합니다. 예를 들어, Predicate<T> 제네릭 대리자를 사용하면 특정 형식에 대한 사용자의 검색 조건을 구현하는 메서드를 만들 수 있으며, Array, Find, FindLast와 같은 FindAll 형식의 메서드와 함께 그 메서드를 사용할 수 있습니다.
제네릭은 동적으로 생성된 코드를 간소화합니다. 동적으로 생성된 코드와 함께 제네릭을 사용하는 경우 형식을 생성할 필요가 없습니다. 이렇게 하면 전체 어셈블리를 생성하는 대신 간단한 동적 메서드를 사용할 수 있는 시나리오 수가 증가합니다. 자세한 내용은 방법: 동적 메서드 정의 및 실행 및 DynamicMethod.을 참조하세요.
다음은 제네릭의 몇 가지 제한 사항입니다.
제네릭 형식은 대부분의 기본 클래스 MarshalByRefObject 에서 파생될 수 있습니다(및 제약 조건은 제네릭 형식 매개 변수가 같은 MarshalByRefObject기본 클래스에서 파생되도록 요구하는 데 사용할 수 있습니다). 그러나 .NET은 컨텍스트 바인딩된 제네릭 형식을 지원하지 않습니다. 제네릭 형식은 ContextBoundObject에서 파생될 수 있지만, 해당 형식의 인스턴스를 만들려고 하면 TypeLoadException가 발생합니다.
열거형에는 제네릭 형식 매개 변수가 있을 수 없습니다. 열거형은 부수적으로만 제네릭일 수 있습니다(예: Visual Basic, C#또는 C++를 사용하여 정의된 제네릭 형식에 중첩되어 있기 때문). 자세한 내용은 공용 형식 시스템의 "열거형"을 참조하세요.
경량 동적 메서드는 제네릭일 수 없습니다.
Visual Basic, C# 및 C++에서는 모든 바깥쪽 형식의 형식 매개 변수에 형식이 할당되지 않은 한 제네릭 형식으로 묶인 중첩 형식을 인스턴스화할 수 없습니다. 이를 말하는 또 다른 방법은 리플렉션에서 이러한 언어를 사용하여 정의된 중첩된 형식에 모든 바깥쪽 형식의 형식 매개 변수가 포함된다는 것입니다. 바깥쪽 형식의 형식 매개 변수를 중첩된 형식의 멤버 정의에서 사용할 수 있게 합니다. 자세한 내용은 MakeGenericType의 "중첩 형식"을 참조하세요.
비고
동적 어셈블리에서 코드를 내보내거나 Ilasm.exe(IL 어셈블러) 를 사용하여 정의된 중첩 형식은 바깥쪽 형식의 형식 매개 변수를 포함할 필요가 없습니다. 그러나 형식 매개 변수를 포함하지 않는 경우 형식 매개 변수는 중첩 클래스의 범위에 없습니다.
자세한 내용은 MakeGenericType의 "중첩 형식"을 참조하세요.
클래스 라이브러리 및 언어 지원
.NET은 다음 네임스페이스에 여러 제네릭 컬렉션 클래스를 제공합니다.
네임스페이스에는 System.Collections.Generic .NET에서 제공하는 대부분의 제네릭 컬렉션 형식(예: List<T>Dictionary<TKey,TValue> 제네릭 클래스)이 포함됩니다.
네임스페이스에는 System.Collections.ObjectModel 개체 모델을 클래스 사용자에게 노출하는 데 유용한 제네릭 클래스와 같은 ReadOnlyCollection<T> 추가 제네릭 컬렉션 형식이 포함되어 있습니다.
정렬 및 같음 비교를 구현하기 위한 제네릭 인터페이스는 이벤트 처리기, 변환 및 검색 조건자의 제네릭 대리자 형식과 함께 네임스페이스에 제공됩니다 System .
네임스페이 System.Numerics 스는 수학 기능을 위한 제네릭 인터페이스를 제공합니다(.NET 7 이상 버전에서 사용 가능). 자세한 내용은 제네릭 수학을 참조하세요.
제네릭 형식과 제네릭 메서드를 검사하기 위한 System.Reflection 네임스페이스, 제네릭 형식과 메서드를 포함하는 동적 어셈블리를 내보내기 위한 System.Reflection.Emit, 그리고 제네릭을 포함하는 원본 그래프를 생성하기 위한 System.CodeDom에 대한 지원이 추가되었습니다.
공용 언어 런타임은 제네릭 형식(CIL, 공용 중간 언어)을 지원하기 위해 Stelem, Ldelem, Unbox_Any, Constrained, 및 Readonly과 같은 새로운 opcode 및 접두사를 제공합니다.
Visual C++, C# 및 Visual Basic은 모두 제네릭을 정의하고 사용하기 위한 모든 지원을 제공합니다. 언어 지원에 대한 자세한 내용은 Visual Basic의 제네릭 형식, 제네릭 소개 및 Visual C++의 제네릭 개요를 참조하세요.
중첩 형식 및 제네릭
제네릭 형식에 중첩된 형식은 바깥쪽 제네릭 형식의 형식 매개 변수에 따라 달라질 수 있습니다. 공용 언어 런타임은 고유한 제네릭 형식 매개 변수가 없는 경우에도 중첩된 형식을 제네릭으로 간주합니다. 중첩 형식의 인스턴스를 만들 때는 모든 묶은 제네릭 형식에 대한 형식 인수를 지정해야 합니다.
관련 문서
제목 | 설명 |
---|---|
.NET의 제네릭 컬렉션 | .NET의 제네릭 컬렉션 클래스 및 기타 제네릭 형식에 대해 설명합니다. |
배열 및 목록을 조작하기 위한 제네릭 대리자 | 배열 또는 컬렉션의 요소에 대해 수행할 변환, 검색 조건자 및 작업에 대한 제네릭 대리자를 설명합니다. |
제네릭 수학 | 수학 연산을 일반적으로 수행하는 방법을 설명합니다. |
제네릭 인터페이스 | 제네릭 형식의 제품군에서 공통 기능을 제공하는 제네릭 인터페이스에 대해 설명합니다. |
공변성 및 반공변성 | 제네릭 형식 매개 변수의 공변성 및 반공변에 대해 설명합니다. |
일반적으로 사용되는 컬렉션 형식 | 제네릭 형식을 포함하여 .NET에서 컬렉션 형식의 특성 및 사용 시나리오에 대한 요약 정보를 제공합니다. |
제네릭 컬렉션을 사용하는 경우 | 제네릭 컬렉션 형식을 사용하는 시기를 결정하는 일반적인 규칙에 대해 설명합니다. |
방법: 리플렉션 내보내기를 사용하여 제네릭 형식 정의 | 제네릭 형식 및 메서드를 포함하는 동적 어셈블리를 생성하는 방법을 설명합니다. |
Visual Basic의 제네릭 형식 | 제네릭 형식을 사용하고 정의하는 방법 항목을 포함하여 Visual Basic 사용자의 제네릭 기능에 대해 설명합니다. |
제네릭 소개 | C# 사용자에 대한 제네릭 형식 정의 및 사용에 대한 개요를 제공합니다. |
Visual C++의 제네릭 개요 | 제네릭과 템플릿 간의 차이점을 포함하여 C++ 사용자의 제네릭 기능에 대해 설명합니다. |
참고 문헌
.NET