전 시간, 제네릭 타입의 제한에 대한 보충...
제네릭 타입의 제한(제약 조건, Constraints) 을 지정할 때,
값 형식(struct)인지 참조 형식(class)인지, 특정 인터페이스를 구현했는지 등을 제한할 수 있다.
이를 활용하면 잘못된 타입이 들어오는 것을 방지하고, 타입 안전성을 확보할 수 있다.
| 제한 조건 | 설명 |
|---|---|
where T : struct | T는 반드시 값 타입(Struct) 이어야 한다. |
where T : class | T는 반드시 참조 타입(Class, Interface, Delegate, Array) 이어야 한다. |
where T : new() | T는 반드시 매개변수가 없는 기본 생성자를 가져야 한다. |
where T : SomeBaseClass | T는 SomeBaseClass를 상속한 클래스여야 한다. |
where T : SomeInterface | T는 SomeInterface를 구현한 타입이어야 한다. |
where T : U | T는 반드시 U를 상속하거나 구현해야 한다. |
where T : struct (값 타입 제한)T는 반드시 값 타입(Struct) 이어야 한다.class 타입을 넣으면 컴파일 오류 발생using System;
public class MyClass { } // 참조 타입
public struct MyStruct { } // 값 타입
public class ValueTypeExample<T> where T : struct
{
public void Print(T value)
{
Console.WriteLine(value);
}
}
class Program
{
static void Main()
{
ValueTypeExample<int> intExample = new ValueTypeExample<int>(); // ✅ 가능 (int는 struct)
intExample.Print(100); // 100 출력
ValueTypeExample<MyStruct> structExample = new ValueTypeExample<MyStruct>(); // ✅ 가능
structExample.Print(new MyStruct());
// ValueTypeExample<MyClass> classExample = new ValueTypeExample<MyClass>(); // ❌ 오류 발생 (MyClass는 참조형)
}
}
100
struct)만 허용되고, 클래스(class)를 사용하면 컴파일 오류가 발생한다.where T : class (참조 타입 제한)T는 반드시 참조 타입(Class, Interface, Delegate, Array) 이어야 한다.struct 타입을 넣으면 컴파일 오류 발생using System;
public class MyClass { } // ✅ 참조 타입
public struct MyStruct { } // ❌ 값 타입
public class ReferenceTypeExample<T> where T : class
{
public void Print(T value)
{
Console.WriteLine(value);
}
}
class Program
{
static void Main()
{
ReferenceTypeExample<MyClass> classExample = new ReferenceTypeExample<MyClass>(); // ✅ 가능
classExample.Print(new MyClass());
ReferenceTypeExample<string> stringExample = new ReferenceTypeExample<string>(); // ✅ 가능
stringExample.Print("Hello");
// ReferenceTypeExample<MyStruct> structExample = new ReferenceTypeExample<MyStruct>(); // ❌ 오류 발생
}
}
class)만 허용되고, 값 타입(struct)을 사용하면 컴파일 오류 발생!where T : new() (기본 생성자 제한)abstract class나 interface는 사용 불가new()가 있는 경우, struct를 사용할 때 Nullable<T>을 허용하지 않는다.using System;
public class MyClass
{
public MyClass() { } // 기본 생성자 ✅
}
public class MyClassWithParams
{
public MyClassWithParams(int value) { } // 기본 생성자 없음 ❌
}
public class DefaultConstructorExample<T> where T : new()
{
public T CreateInstance()
{
return new T(); // 매개변수 없는 생성자 호출 가능
}
}
class Program
{
static void Main()
{
DefaultConstructorExample<MyClass> obj1 = new DefaultConstructorExample<MyClass>(); // ✅ 가능
MyClass instance1 = obj1.CreateInstance();
// DefaultConstructorExample<MyClassWithParams> obj2 = new DefaultConstructorExample<MyClassWithParams>(); // ❌ 오류 발생
}
}
MyClassWithParams)를 사용하면 컴파일 오류 발생!where T : SomeBaseClass (상속 제한)T는 반드시 SomeBaseClass를 상속해야 한다.using System;
public class Animal { } // 부모 클래스
public class Dog : Animal { } // ✅ 상속받은 클래스
public class Cat : Animal { } // ✅ 상속받은 클래스
public class Car { } // ❌ 다른 클래스
public class AnimalExample<T> where T : Animal
{
public void Print(T animal)
{
Console.WriteLine(animal.GetType().Name);
}
}
class Program
{
static void Main()
{
AnimalExample<Dog> dogExample = new AnimalExample<Dog>(); // ✅ 가능
dogExample.Print(new Dog()); // Dog 출력
AnimalExample<Cat> catExample = new AnimalExample<Cat>(); // ✅ 가능
catExample.Print(new Cat());
// AnimalExample<Car> carExample = new AnimalExample<Car>(); // ❌ 오류 발생 (Car는 Animal을 상속하지 않음)
}
}
Animal을 상속한 Dog, Cat은 가능하지만, Car는 오류가 발생한다.where T : SomeInterface (인터페이스 구현 제한)T는 반드시 SomeInterface를 구현해야 한다.using System;
public interface IMovable
{
void Move();
}
public class Car : IMovable
{
public void Move() => Console.WriteLine("Car is moving");
}
public class Animal { } // ❌ IMovable 미구현
public class MovableExample<T> where T : IMovable
{
public void ExecuteMove(T obj)
{
obj.Move();
}
}
class Program
{
static void Main()
{
MovableExample<Car> carExample = new MovableExample<Car>(); // ✅ 가능
carExample.ExecuteMove(new Car());
// MovableExample<Animal> animalExample = new MovableExample<Animal>(); // ❌ 오류 발생
}
}
IMovable 인터페이스를 구현한 Car는 가능하지만, Animal은 오류가 발생한다.where T : U (타입 상속 제한)T는 반드시 U를 상속 또는 구현해야 한다.using System;
public class BaseClass { }
public class DerivedClass : BaseClass { }
public class GenericExample<T, U> where T : U
{
public void Print(T value)
{
Console.WriteLine(value.GetType().Name);
}
}
class Program
{
static void Main()
{
GenericExample<DerivedClass, BaseClass> example = new GenericExample<DerivedClass, BaseClass>(); // ✅ 가능
example.Print(new DerivedClass());
// GenericExample<BaseClass, DerivedClass> invalidExample = new GenericExample<BaseClass, DerivedClass>(); // ❌ 오류 발생
}
}
T가 U를 상속해야 하는데, BaseClass가 DerivedClass를 상속하지 않으므로 오류가 발생한다.| 제한 조건 | 설명 |
|---|---|
| where T : struct | T는 값 타입(struct) 이어야 한다. |
where T : class | T는 참조 타입(class, interface, delegate, array) 이어야 한다. |
where T : new() | T는 매개변수 없는 기본 생성자를 가져야 한다. |
where T : SomeBaseClass | T는 SomeBaseClass를 상속해야 한다. |
where T : SomeInterface | T는 SomeInterface를 구현해야 한다. |
where T : U | T는 반드시 U를 상속 또는 구현해야 한다. |