본문 바로가기
프로그래밍/C# .NET

제네릭 (2)

by 개발하는군인 2023. 4. 17.

1편에 이어서 제네릭의 타입제한 및  BCL에 적용된 제네릭에 대해서 정리하겠다. 시작 하기전에 앞서 앞서 배운 내용을 정리하자면,  제네릭이 도입 되기전에는  Object 형식의 배열 형태로  다양한 타입을 입력 받아 관리 하였으나, 박싱/언박싱 문제로 비효율적인 메모리 사용 문제가 발생하였고 이 문제를 해결하기위해 다양한 타입의 함수를 작성하여 처리하였으나, 중복의 문제가 발생하였다. 이러한 문제를 해결하기 위한 방법으로 제네릭을 사용한다.  제네릭 타입의로 지정 시 

CLR은 JIT 컴파일 시에 클래스가 타입에 따라 정의 될때마다 T에 대응되는 타입을 대체해서 확장한다. 즉 매개변수 전달 타입에 따라 N개의 클래스에 해당하는 기계어 코드가 자동으로 만들어 진다는 뜻이다.

 

정리하자면 제네릭의 사용은 박싱/언박싱으로 발생하는 비효율적인 힙 메모리 사용 문제를 없앨뿐더러 데이터  타입에 따른 코드 중복 문제도 해결해 준다.

 

 

형식 매개변수에 대한 제약 조건 

 

제네릭을 사용하다 보면 형식 매개변수로 받아들이는 타입이 특정 조건을 만족해야만 할 때가 있다. 

 

해당 코드를 사용하면 T에 CompareTo 에 대한 정의가 없고 T 형식의 첫번째 인수를 허용하는 확장 메서드

CompareTo 가 없습니다. 라는 오류가 발생한다. T로 대체하는 타입이 모두 CompareTo를 지원하는게

아니므로 컴파일 단계에서 오류를 발생시켜 잘못된 사용을 막는 것이다.  바로 이런 경우에 

T에 입력될수 있는 타입의 조건 Where 예약어를 사용해 제한 할 수 있다.

T 의 Compare 사용 오류

 

where 예약어 다음에 형식 매개변수를 지정하고 콜론(:) 구분자로 사용해 제약 조건을 걸 수 있다. 

컴파일러는 IComparable 인터페이스를 상속 받은 타입의 인스턴스라고 가정하게 되고 코드에서 

Comparto 메서드를 호출하는것을 허용한다.

 

IComparable 을 상속 받은 타입만 매개변수로 받는다.

 

추가적 으로 지원하는 제약 조건 이다.

 

where  T : struct   값 형식만 가능하다.

where  T : class   참조 형식만 가능하다.

where  T : new() 매개변수 없는 공용 생성자가 포함돼 있어야 한다.

where T : U  U형식 인수에 해당하는 타입이거나 그것으로부터 상속 받은 클래스만 가능하다.

 

 

해당 코드를 실행하면 값 형식의 바이트 크기를 반환하는 코드이다. 제약조건이 없고 값 형식이 아닌 참조형식

을 전달한다면  컴파일시에는 문제 없이 동작하나 실행시에는  오류가 발생할 것이다.

 

실행 시간에 오류를 발생 시키는 것보다 컴파일 타임에서 오류를 찾을 수 있다면, 훨씬 빠르고 쉽게 

오류를 찾아 낼 수 있다.

 

두번째 예제는 해당 값이 null 인지 아닌지 확인하는 코드이다. 모든 값 형식은 null 상태를 갖지 않으므로 

참조 형식에 적용하는게 올바르기 때문에 class 제약조건을 걸어 사용한다.

 

 

 

마무리

 

요번 내용을 정리하자면 제네릭은 컴파일 타임이 아니라 매개변수가 전달될때 그 값이 결정된다.

 

이말은 즉슨 위와같이 값 형식의 null을 검사하거나, 특정 형식만 지원하는 함수가 내부에서 동작할 경우에

컴파일 시에는 문제 없이 동작하나  실행 시 문제가 발생할 여지가 있다는 것이다. 제약조건을 명시하므로써

에러가 발생하는 부분을 컴파일 시부터 확인하여 손 쉽게 에러 핸들링을 할 수 있다.

 

 

'프로그래밍 > C# .NET' 카테고리의 다른 글

세션 유휴 타이머  (0) 2025.04.10
제네릭  (0) 2023.04.16
C# Invoke, BeginInvoke  (0) 2023.04.02
다양한 로그 수집 하기  (0) 2023.03.27
BCL (1)  (0) 2023.03.25