ShovelingLife
A Game Programmer
ShovelingLife
전체 방문자
오늘
어제
  • 분류 전체보기 (1074)
    • 그래픽스 (57)
      • 공통 (19)
      • 수학 물리 (22)
      • OpenGL & Vulkan (1)
      • DirectX (14)
    • 게임엔진 (183)
      • Unreal (69)
      • Unity (103)
      • Cocos2D-X (3)
      • 개인 플젝 (8)
    • 코딩테스트 (221)
      • 공통 (7)
      • 프로그래머스 (22)
      • 백준 (162)
      • LeetCode (19)
      • HackerRank (2)
      • 코딩테스트 알고리즘 (8)
    • CS (235)
      • 공통 (21)
      • 네트워크 (44)
      • OS & 하드웨어 (55)
      • 자료구조 & 알고리즘 (98)
      • 디자인패턴 (6)
      • UML (4)
      • 데이터베이스 (7)
    • 프로그래밍 언어 (349)
      • C++ (168)
      • C# (90)
      • Java (9)
      • Python (33)
      • SQL (30)
      • JavaScript (8)
      • React (7)
    • 그 외 (10)
      • Math (5)
      • 일상 (5)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • Source Code 좌측 상단에 복사 버튼 추가 완료
  • 언리얼 엔진 C++ 빌드시간 단축 꿀팁
  • 게임 업계 코딩테스트 관련
  • 1인칭 시점으로 써내려가는 글들

인기 글

태그

  • 유니티
  • 클래스
  • 알고리즘
  • 배열
  • 그래픽스
  • c#
  • 오블완
  • 언리얼
  • C++
  • 백준
  • 프로그래머스
  • C
  • SQL
  • 티스토리챌린지
  • 함수
  • 문자열
  • Unity
  • 포인터
  • string
  • 파이썬

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ShovelingLife

A Game Programmer

C# 제네릭 (C++ > 템플릿)
프로그래밍 언어/C#

C# 제네릭 (C++ > 템플릿)

2022. 6. 13. 11:03
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
    '프로그래밍 언어/C#' 카테고리의 다른 글
    • C# static (정적) 메서드와 클래스
    • C# Boxing Unboxing 박싱 언박싱 값>참조, 참조>값
    • C# Delegate Event 사용법
    • C# 사용자 정의 전환 연산자(암시적/명시적)
    ShovelingLife
    ShovelingLife
    Main skill stack => Unity C# / Unreal C++ Studying Front / BackEnd, Java Python

    티스토리툴바