English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
일반화는 특정 형식이 아니라 일반 형식을 의미합니다. C#에서 일반화는 특정 데이터 타입에 특정하지 않다는 것을 의미합니다.
C#은 타입 파라미터를 사용하여 특정 데이터 타입 없이 일반화된 클래스, 인터페이스, 추상 클래스, 필드, 메서드, 스태틱 메서드, 프로퍼티, 이벤트, 대리자 및 연산자를 정의할 수 있습니다. 타입 파라미터는 일반화된 타입의 인스턴스를 생성할 때 특정 타입으로 지정되는 대체자입니다.
타입 이름 뒤의 괄호에서 타입 파라미터를 지정하여 일반화를 선언합니다. 예를 들어, TypeName<T>에서 T는 타입 파라미터입니다.
일반화된 클래스는 클래스 이름 뒤의 괄호에서 타입 파라미터를 사용하여 정의됩니다. 아래는 일반화된 클래스를 정의한 예입니다.
class DataStore<T> { public T Data { get; set; } }
위에서 DataStore는 일반화된 클래스입니다. T는 타입 파라미터로, DataStore 클래스의 필드, 프로퍼티, 메서드 파라미터, 반환 타입 및 DataStore 클래스의 대리자의 타입으로 사용됩니다. 예를 들어, Data는 타입 파라미터 T를 사용하여 특정 데이터 타입이 아닌 타입으로 정의된 일반화된 프로퍼티입니다.
또한 여러 타입 파라미터를 정의하고 쉼표로 구분할 수 있습니다.
class KeyValuePair<TKey, TValue> { public TKey Key { get; set; } public TValue Value { get; set; } }
尖括号에 실제 타입을 지정하여 제네릭 클래스의 인스턴스를 생성할 수 있습니다. DataStore의 인스턴스를 생성하겠습니다.
DataStore<string> store = new DataStore<string>();
위에서 string을 인스턴스 생성 시 괄호로 지정하면, T는 컴파일 시 string으로 대체되어 전체 클래스에서 사용된 T의 모든 타입을 대체합니다. 따라서 Data 속성의 타입은 string입니다.
아래 그림은 제네릭의 작동 방식을 설명합니다.
Data属性에 문자열 값을 할당할 수 있습니다. 문자열 이외의 값을 할당하려고 시도하면 컴파일 시 오류가 발생합니다.
DataStore<string> store = new DataStore<string>(); store.Data = "Hello World!";//obj.Data = 123; //컴파일 시 오류
다른 객체에 다른 데이터 타입을 지정할 수 있습니다. 예를 들어 다음과 같이 합니다.
DataStore<string> strStore = new DataStore<string>(); strStore.Data = "Hello World!"; //strStore.Data = 123; // 컴파일 시 오류 DataStore<int> intStore = new DataStore<int>(); intStore.Data = 100; //intStore.Data = "Hello World!"; // 컴파일 시 오류 KeyValuePair<int, string> kvp1 = new KeyValuePair<int, string>(); kvp1.Key = 100; kvp1.Value = "Hundred"; KeyValuePair<string, string> kvp2 = new KeyValuePair<string, string>(); kvp2.Key = "IT"; kvp2.Value = "Information Technology";
제네릭 클래스는 재사용성을 높입니다. 타입이 많을수록 재사용성이 높아집니다. 그러나, 과도한 일반화는 코드를 이해하고 유지보수하기 어려워집니다.
제네릭 클래스는 다른 제네릭이나 비제네릭 클래스나 추상 클래스의 기본 클래스가 될 수 있습니다.
제네릭 클래스는 다른 제네릭이나 비제네릭 인터페이스, 클래스, 추상 클래스에서 자기 자신을 상속할 수 있습니다.
제네릭 클래스는 제네릭 필드를 포함할 수 있습니다. 그러나, 초기화할 수 없습니다.
class DataStore<T> { public T data; }
아래에서 제네릭 배열을 선언합니다.
class DataStore<T> { public T[] data = new T[10]; }
타입 파라미터를 사용하여 반환 타입이나 파라미터를 선언하는 메서드는 제어 메서드라고 합니다.
class DataStore<T> { private T[] _data = new T[10]; public void AddOrUpdate(int index, T item) { if(index >= 0 && index < 10) _data[index] = item; } public T GetData(int index) { if(index >= 0 && index < 10) return _data[index]; else return default(T); } }
위의 AddorUpdate()과 GetData() 메서드는 제어 메서드입니다. item 파라미터의 실제 데이터 타입은 DataStore<T> 클래스를 인스턴스화할 때 지정됩니다. 예를 들어 다음과 같습니다.
DataStore<string> cities = new DataStore<string>(); cities.AddOrUpdate(0, "Mumbai"); cities.AddOrUpdate(1, "Chicago"); cities.AddOrUpdate(2, "London"); DataStore<int> empIds = new DataStore<int>(); empIds.AddOrUpdate(0, 50); empIds.AddOrUpdate(1, 65); empIds.AddOrUpdate(2, 89);
제어 파라미터 타입은 비제어 파라미터와 반환 타입이 있는 여러 파라미터와 함께 사용될 수 있습니다. 다음은 유효한 제어 메서드 오버로드입니다.
public void AddOrUpdate(int index, T data) { } public void AddOrUpdate(T data1, T data2) { } public void AddOrUpdate<U>(T data1, U data2) { } public void AddOrUpdate(T data) { }
尖括号에서 메서드 이름을 사용하여 타입 파라미터를 지정하여 비제어 타입 클래스는 제어 메서드를 포함할 수 있습니다. 예를 들어 다음과 같습니다.
class Printer { public void Print<T>(T data) { Console.WriteLine(data); } } Printer printer = new Printer(); printer.Print<int>(100); printer.Print(200); // 지정된 값에 따라 추론 printer.Print<string>("Hello"); printer.Print("World!"); // 지정된 값에 따라 추론
Generics는 코드의 재사용성을 높입니다. 다른 데이터 타입을 처리하는 코드를 작성할 필요가 없습니다.
Generics는 타입 안전합니다. 정의된 데이터 타입과 다른 데이터 타입을 사용하려고 시도할 때 컴파일 시에 오류가 발생합니다.
Generics는 패킹과 언패킹 가능성을 제거하여 성능 이점을 가지고 있습니다.