using System;
public class Test<T> where T : class
{
public T Get_val(T _val)
{
return _val;
}
}
public class Another
{
public static void Main()
{
Test<int> int_test = new Test<int>();
Console.WriteLine(int_test.Get_val(10));
}
}
첫째 클래스 선언 라인에 보면 where T : class라고 명시 되어있다, Main 함수 내에 선언하고 있는건 int형이다, 따라서 아래와 같이 에러가 뜬다.
C++와 가장 큰 차이점은 C#의 템플릿은 제약 사항이 많다는 것이다, SFINAE도 있겠지만 가장 큰 특징은 추상화를 할 수 없다는 점이다 따라서 아래는 에러가 뜬다.
using System;
public class Test<T> where T : class
{
public static void Print(T _pos)
{
Console.WriteLine(String.Format("x값 : {0}, y값 : {1}"), _pos.x, _pos.y);
}
}
public class Pos
{
public int x, y;
public Pos()
{
}
public Pos(int x, int y)
{
this.x = x;
this.y = y;
}
}
public class Another
{
public static void Main()
{
Test<Pos>.Print(new Pos(5, 7));
}
}
살짝 바꿔보면 아래와 같이 정상적으로 출력되는 모습을 볼 수 있다.
using System;
public class Pos
{
public int x, y;
public Pos()
{
}
public Pos(int x, int y)
{
this.x = x;
this.y = y;
}
}
public class Test<T> where T : Pos
{
public static void Print(T _pos)
{
Console.WriteLine($"x값 :{_pos.x}, y값 : {_pos.y}");
}
}
public class Another
{
public static void Main()
{
Test<Pos>.Print(new Pos(5, 7));
}
}
근데 만약에 여러 클래스를 받고싶다면 어떻게 해야할까? where T : Pos 이 부분에서 Pos를 class로 다시 바꿔주고 리플렉션 기능을 사용해야 한다, System.Type 하지만 C#에선 룰이 존재한다, 바로 switch가 안된다는 부분이다.
public class Test<T> where T : class
{
public static void Print(T _pos)
{
Type type = _pos.GetType();
switch(type)
{
case typeof(int):
break;
}
}
}
이렇게 선언할 시 아래와 같은 에러가 뜬다.
부모 클래스로부터 상속을 받아 오버라이딩한 후 Print함수에서 부모 클래스로 캐스팅을 하여 널이 아닐 시 출력하는 예제. Dog Cat 두 클래스 모두 다 Animal로부터 상속을 받기 때문에 as로 캐스팅 할 시 널이 될 수가 없다.
using System;
public class Animal
{
string sound_type = "";
public Animal(string _sound_type)
{
this.sound_type = _sound_type;
}
public virtual void Play_sound()
{
Console.WriteLine(sound_type);
}
}
public class Dog : Animal
{
public Dog(string _sound_type) : base(_sound_type)
{
}
public override void Play_sound()
{
Console.WriteLine("이건 강아지 ");
base.Play_sound();
}
}
public class Cat : Animal
{
public Cat(string _sound_type) : base(_sound_type)
{
}
public override void Play_sound()
{
Console.WriteLine("이건 고양이 ");
base.Play_sound();
}
}
public class Test<T> where T : class
{
public void Print(T _type)
{
Animal animal = _type as Animal;
if (animal != null)
animal.Play_sound();
}
}
public class Another
{
public static void Main()
{
Test<Animal> animal_test = new Test<Animal>();
animal_test.Print(new Dog("멍멍"));
animal_test.Print(new Cat("냐옹"));
}
}
마지막으로 템플릿 함수에 대해 알아보겠다.
using System;
public class A
{
public void Print()
{
Console.WriteLine("A 클래스");
}
}
public class B
{
public void Print<T>(T _t) where T : A
{
_t.Print();
}
}
public class C
{
public void Print<T>(T _t) where T : A
{
_t.Print();
}
public void Print()
{
Console.WriteLine("C 클래스");
}
}
public class D<T> : A where T : class
{
public void Test(T _t)
{
Type type = _t.GetType();
if(type == typeof(C))
{
C c = _t as C;
c.Print();
}
}
}
public class Test
{
public static void Main()
{
B b = new B();
A a = new A();
C c = new C();
D<C> d = new D<C>();
b.Print<A>(a);
c.Print<A>(a);
d.Print();
d.Test(c);
}
}
여기 메인 함수에서 에러를 뜨는 이유를 보자. D 클래스는 where절로 class라고 명시 되어있다, int형은 클래스가 아니므로 에러가 뜬다. c클래스 내에 Print 함수는 where절로 A클래스라고 명시 되어있다 따라서 에러가 뜬다, 추가적으로 덧붙이자면 Print 함수에서 꺽쇠 괄호 <클래스명> 클래스 명시는 생략해도 무방하다.
'프로그래밍 언어 > C#' 카테고리의 다른 글
C# static (정적) 메서드와 클래스 (0) | 2022.06.24 |
---|---|
C# Boxing Unboxing 박싱 언박싱 값>참조, 참조>값 (0) | 2022.06.19 |
C# Delegate Event 사용법 (0) | 2022.06.08 |
C# 사용자 정의 전환 연산자(암시적/명시적) (0) | 2022.06.08 |
C# LINQ (0) | 2022.06.07 |