제네릭 클래스와 제네릭 메서드는 재사용성, 유형 안전성 및 고효율성을 결합하며 이는 해당 비제네릭 클래스 및 메서드의 범위를 벗어납니다. 제네릭은 컨테이너(컬렉션) 및 컨테이너에서 작동하는 메서드에 널리 사용됩니다. .NET Framework 2.0 클래스 라이브러리는 몇 가지 새로운 제네릭 기반 컨테이너 클래스를 포함하는 새로운 네임스페이스 System.Collections.Generic을 제공합니다.
제네릭의 변수 유형 매개변수: T가 일반적으로 사용되지만 키워드가 아닌 단어와 예약어도 사용할 수 있습니다.
모든 변수 유형 T는 컴파일 시 자리 표시자를 사용합니다. 모든 점 기호는 런타임에 전달된 실제 유형으로 대체됩니다.
초기 버전의 공용 언어 런타임 및 C# 언어 제한 사항에 대해 제네릭은 솔루션을 제공합니다. 이전 유형의 일반화는 유형을 전역 기본 클래스 System.Object로 변환하여 달성되었습니다. .NET Framework 기본 클래스 라이브러리의 ArrayList 컨테이너 클래스가 이러한 제한 사항의 예입니다. ArrayList는 사용 중에 참조 유형이나 값 유형을 변경하지 않고 저장할 수 있는 매우 편리한 컨테이너 클래스입니다.
ArrayList list = new ArrayList(); double sum = 0; |
단점:
편의성에는 대가가 따르기 때문에 ArrayList에 추가된 모든 참조 유형이나 값 유형을 탄력적으로 숨겨야 합니다. System.Object로 업캐스트됩니다. 요소가 값 유형인 경우 목록에 추가할 때 boxing하고 검색할 때 unboxing해야 합니다. 유형 변환, 박싱 및 언박싱 작업은 모두 성능을 저하시키며, 대형 컨테이너를 반복해야 하는 경우 박싱 및 언박싱의 영향이 심각할 수 있습니다. 또 다른 제한 사항은 컴파일 시간 유형 검사가 부족하다는 것입니다. ArrayList가 모든 유형을 Object로 변환하면 컴파일 시간에 고객 코드에서 sum+=vlaue와 같은 오류를 방지할 수 없습니다.
System.Collections.Generic 네임스페이스에서; List
List 3. 제네릭 유형 매개변수 |
List
제네릭은 다음과 같은 5가지 제약을 제공합니다:
제약 조건이 일반 유형 매개 변수인 경우 이를 Naked 유형 제약 조건이라고 합니다. class List 위 예에서 Add 메서드 컨텍스트의 T는 형식화되지 않은 제약 조건인 반면 List 클래스 컨텍스트의 T는 무제한 형식 매개 변수입니다. 형식화되지 않은 제약 조건은 일반 클래스 정의에도 사용할 수 있습니다. 유형이 지정되지 않은 제약 조건은 다른 유형 매개 변수와 함께 꺾쇠 괄호 안에 선언해야 합니다. //naked 유형 제약 조건 public class MyClass 컴파일러는 형식화되지 않은 제약 조건만 System.Object에서 상속되는 것으로 간주하므로 형식화되지 않은 제약 조건이 있는 일반 클래스의 사용은 매우 제한됩니다. 두 유형 매개변수 간의 상속 관계를 적용하려면 제네릭 클래스에 유형화되지 않은 제약 조건을 사용하세요. 일반 클래스는 특정 데이터 유형에 국한되지 않는 작업을 캡슐화합니다. 일반 클래스는 연결 목록, 해시 테이블, 스택, 큐, 트리 등과 같은 컨테이너 클래스에서 자주 사용됩니다. 컨테이너에서 요소를 추가하고 제거하는 등 이러한 클래스의 작업은 저장된 데이터 유형에 관계없이 거의 동일한 작업을 수행합니다. 일반적으로 기존의 구체적인 클래스에서 일반 클래스를 만들고 일반성과 유용성 사이에서 최상의 균형을 얻을 때까지 한 번에 하나씩 유형 매개변수로 유형을 변경합니다. 자신만의 일반 클래스를 만들 때 고려해야 할 중요한 사항은 다음과 같습니다. 어떤 유형을 유형 매개변수로 일반화해야 하는지. 일반적인 규칙은 매개변수로 표현되는 유형이 많을수록 코드의 유연성과 재사용성이 높아진다는 것입니다. 너무 많은 일반화는 다른 개발자가 코드를 이해하기 어렵게 만들 수 있습니다. 제약조건이 있는 경우 유형 매개변수에는 어떤 종류의 제약조건이 필요합니까? 좋은 방법은 처리해야 하는 모든 유형이 처리될 수 있도록 보장하면서 가능한 가장 큰 제약 조건을 사용하는 것입니다. 예를 들어, 일반 클래스가 참조 유형만 사용한다는 것을 알고 있다면 해당 클래스에 대한 제약 조건을 적용하세요. 이를 통해 실수로 값 유형을 사용하는 것을 방지하고 T에서 as 연산자를 사용하고 기본 클래스 또는 하위 클래스에 일반 동작을 배치할 수 있습니다. 일반 클래스를 기본 클래스로 사용할 수 있습니다. 이는 제네릭이 아닌 클래스를 디자인할 때도 고려해야 합니다. 일반 기본 클래스에 대한 상속 규칙 하나 이상의 일반 인터페이스를 구현할지 여부. 예를 들어 제네릭 기반 컨테이너에서 요소를 생성하는 클래스를 디자인하려면 IComparable 일반 클래스 Node // 구상 유형 비제네릭 구체적 클래스는 폐쇄형 구성 기본 클래스에서 상속할 수 있지만 개방형 구성 기본 클래스에서는 상속할 수 없습니다. 수업. 이는 클라이언트 코드가 기본 클래스에 필요한 유형 매개변수를 제공할 수 없기 때문입니다. //오류 없음. 일반 유형의 구체적인 클래스는 개방형 생성 유형에서 상속할 수 있습니다. 하위 클래스와 공유되는 유형 매개변수를 제외하고 모든 유형 매개변수에 유형을 지정해야 합니다. //오류를 생성합니다. 개방형 구조 유형, 매개변수 유형 및 제약 조건을 지정해야 합니다. class MyNodeItem 일반 유형은 다양한 유형 매개변수 및 제약조건을 사용할 수 있습니다. class SuperKeyType 개방형 및 폐쇄형 생성 유형을 메소드의 매개변수로 사용할 수 있습니다: void Swap 인터페이스를 유형 매개변수에 대한 제약조건으로 지정하는 경우 해당 인터페이스를 구현하는 유형만 사용할 수 있습니다. 매개변수를 입력합니다. 다음과 같이 여러 인터페이스를 유형의 제약 조건으로 지정할 수 있습니다. 인터페이스는 다음과 같이 여러 유형 매개변수를 정의할 수 있습니다.
IMyInterface //Okay.class MyClass
T temp;
유형 매개변수를 무시할 수도 있으며 컴파일러는 가서 추론해 보세요. Swap을 호출하는 다음 코드는 위의 예제와 동일합니다.
Swap(a, b); { void Swap(ref T lhs, ref T rhs) { ... }}
제네릭 클래스에서 정의되지 않은 유형 매개변수를 정의하는 제네릭 메서드를 정의합니다. (일반적으로 사용되지 않음, 일반적으로 제약 조건과 함께 사용됨) class List void add; u & gt; (list & lt; u & gt; 항목) 여기서 u : t {} // 일반적으로 사용되는}} 일반 메소드는 여러 유형 매개변수로 오버로드됩니다. 예를 들어, 다음 메서드를 동일한 클래스에 배치할 수 있습니다. void DoSomething 제네릭 클래스 및 제네릭 메소드에서 발생하는 문제는 매개변수화된 유형에 기본값을 할당하는 방법을 현재로서는 알 수 없습니다. 다음 두 가지 사항을 미리 확인하세요. T는 값 유형 또는 참조 유형이 됩니다. T가 값 유형이면 T는 숫자 값 또는 구조가 됩니다. 매개변수화된 유형의 경우 T의 변수 t에 대해 t = null 문은 T가 참조 유형인 경우에만 유효합니다. t = 0은 숫자 값에만 유효하고 구조에는 유효하지 않습니다. 이 문제에 대한 해결책은 참조 유형에 대해 null을 반환하고 값 유형에 대해 0을 반환하는 default 키워드를 사용하는 것입니다. 구조의 경우 구조의 각 멤버를 반환하고 멤버가 값 유형인지 참조 유형인지에 따라 0 또는 null을 반환합니다. 4. 제네릭 유형 매개변수에 대한 제약
제한되지 않은 유형 매개변수:
Constraint
Description
여기서 T : class여기서 T: 매개변수 유형은 값이어야 합니다.
여기서 T : new()매개변수 유형은 참조 유형이어야 합니다
여기서 T : <기본 클래스 이름>매개변수 유형에는 인수가 없는 공개 생성자가 있어야 합니다. 다른 제약 조건과 함께 사용되는 경우 new() 제약 조건은 마지막에 배치되어야 합니다.
여기서 T: <인터페이스 이름>매개변수 유형은 지정된 기본 유형이거나 지정된 기본 유형에서 파생된 하위 클래스여야 합니다.
매개변수 유형 지정된 인터페이스이거나 지정된 인터페이스의 구현이어야 합니다. 여러 인터페이스에 대해 제약 조건을 지정할 수 있습니다. 인터페이스 제약조건은 일반적일 수도 있습니다.
5. 일반 클래스
class Node
//폐쇄형 생성 유형
class Node
//open constructor type
class Node
class Node : BaseNode
//오류를 생성합니다.
class Node: BaseNode< T>
class Node
class Node
class NodeItem
class KeyType
void Swap(List 6. 일반 인터페이스
IDictionary
//알겠습니다.
IMyInterface: IBaseInterface
//알겠습니다. class MyClass
제네릭 메소드는 다음과 같이 유형 매개변수를 선언하는 메소드입니다.
7. 제네릭 메소드
일반 클래스, 일반 구조 및 일반 인터페이스에는 모두 동일한 메서드 오버로드 규칙이 있습니다.
void Swap rhs = temp;} { lhs = rhs;
Swap다음 샘플 코드는 int를 유형 매개변수로 사용하여 메소드를 호출하는 예를 보여줍니다. int b = 2;//… int a = 1;
class List
정적 메서드와 인스턴스 메서드는 동일한 유형 추론 규칙을 갖습니다. 컴파일러는 전달된 메서드 매개변수를 기반으로 형식 매개변수를 추론할 수 있습니다. 이는 제약 조건이나 반환 값만으로는 결정할 수 없습니다. 따라서 매개변수가 없는 메소드의 경우 유형 추론이 유효하지 않습니다. 형식 유추는 컴파일러가 오버로드된 메서드 플래그를 확인하기 전인 컴파일 타임에 발생합니다. 컴파일러는 동일한 이름을 가진 모든 제네릭 메서드에 형식 유추 논리를 적용합니다. 오버로딩 확인 단계에서 컴파일러는 형식 유추에 성공한 제네릭 클래스만 포함합니다.
일반 클래스에서 제네릭이 아닌 메서드는 클래스의 유형 매개변수에 액세스할 수 있습니다.
class List
일반 클래스에서 해당 클래스와 동일한 유형 매개변수를 사용하여 일반 메소드를 정의하면 컴파일러에서 경고 CS0693을 생성합니다. .
{
void Swap< u & gt; (ref t lhs, ref t rhs) {// 일반적으로 사용되지 않음
8. 제네릭의 기본 키워드
void DoSomething() { }
void DoSomething
class GenericClass <
위 내용은 제네릭의 개요 및 구체적인 용도의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!