제약이 붙은 제네릭 클래스
어떠한 형태로도 받아 들이는 제네릭은 강력하다. 이러한 제네릭의 <T> 는 대부분의 클래스가 될 수 있다.
 
그 강력함을 제약해 사용하기 쉽게 하는 수단이 있다. 구체적으로는, 형 파라메터에 제약 리스트를 붙일 수 있다는 것이다. 제약 리스트에는, 클래스나 인터페이스, 생성자의 제약을 지정할 수 있다.
 
이용 빈도는 낮다고 생각되기 때문에 자세한 설명을 하지 않는다.
아래의 샘플을 보자. 리스트12는 인터페이스 제약, 생성자 제약을 붙였다.
 
using System;
 
// IDisposable 인터페이스를실장한다Sample 클래스
public class Sample : IDisposable
{
 public void Dispose()
 {
    Console.WriteLine("Disposed");
 }
}
 
// 제약이붙었다MyClass<T> 클래스
public class MyClass<T> where T : IDisposable, new()
{
 public T Value = new T();
 
 public void Close()
 {
    Value.Dispose();
 }
}
 
class Program
{
 static void Main(string[] args)
 {
    MyClass<Sample> sample = new MyClass<Sample>();
    sample.Close(); // 출력:Disposed
 }
}
리스트12 제약이 붙은 제네릭 클래스의 예
 
여기에 제약을 붙이고 있는 것은,
 
where T : IDisposable, new()
 
부분이다. Where 는 클래스의 제약을 나타내고, T 에 대한 제약을 의미한다. 그 이후 쓰여진 인터페이스명의 IDisposable 은 형 파라메터 T 에 IDisposable 인터페이스를 구현한 형태에만 지정할 수 있다. 추가로 콤마로 구분하여 new() 는 형 파라메터에 T의 형에 인수가 없는 생성자로 제약한다.
 
이 제약은, 단지 사용법에 제한을 두는 것은 아니다.
MyClass<T> 클래스 내에서,
 
Value.Dispose();
 
처럼 사용한다.(IDisposable 인터페이스의) Dispose 메서드를 호출할 수 있는 것은, 반드시 IDisposable 인터페이스를 구현해야 한다고 하는 제약이 있기 때문이다. IDisposable 인터페이스의 제약이 없으면, T 에 Dispose 메서드가 존재하는지 아닌지는 예측 불가능하고, 컴파일 에러가 된다.
 
,
 
public T Value = new T();
 
를 사용할 수 있는 것은, 생성자 제약에 의해 T 에는 인수가 없는 생성자가 존재하면 사용할 수 있도록 제약했기 때문이다. 만약 그러한 제약이 없으면 T 에 인수가 없는 생성자가 있는지 아닌지는 예측하지 못하고, 컴파일 에러가 난다.
 
Posted by 땡초 POWERUMC
TAG ,

댓글을 달아 주세요