일반화(Generic)

이승한·2023년 7월 8일
0

CSharp

목록 보기
8/25

나만의 특별한 리스트를 만들고 싶다고 가정할 때 데이터 형식을 여러가지 지원을 해줘야하는데
무식한 방법으로는 버전마다 하나씩 만들어주는 것

class Program
{
	class MyIntList
    {
    	int[] arr = new int[10];
    }
    class MyFloatList
    {
    	float[] arr = new float[10];
    }
    //......
}

이런식으로 하나씩 다 만드는 것은 너무 비효율적이다.

다른 방법으로는 무엇이 있을까 ?

1.모든 타입을 다 소화할 수있는 object 타입을 사용하는 것

static void Main(string[] args)
{
	object obj = 3;
    object obj2 = "hello world";
    int num = (int)obj;
    string str = (string)obj2;
}

object의 장점은 모든 타입을 소화 가능 하다는 것인데

그렇다면 var 이라는 타입도 비슷한 동작을 했는데 var과 object는 개념이 다르다.

예를 들어,

var obj4 = "hello world";

var은 그냥 뒤에 string이 온것을 보고 string 타입으로 지정을 해주는 것이다.
뒤에 뭐가 오냐에 따라 알아서 변환을 해준다고 생각하면 된다.
그래서 위에 코드는 그냥 string obj4 = "hello world"; 랑 같은 코드인 것이다.

반면에, object는 그냥 object라는 타입이다.

결국에는 상속을 배울 때 클래스를 최상위 부모클래스로 변환이 가능하다는 것을 알았는데
C#에서는 우리가 사용하는 int,string과 같은 타입들이 결국 object를 상속 받아서 구현이 되어있고 그래서 위와 같이 obj , obj2가 가능한것이다.

그러면 모든 타입을 object를 사용하면 되지않을까? 라는 의문이 생긴다.
결론적으로는 속도가 느려진다는 단점이 있다.

int number = 3;

이런식으로 int로 선언한 변수는 stack에서 복사타입으로 3을 저장하며 간단히 사용 할 수있지만

object obj = 3;

이라고 선언할 경우 heap 영역에 메모리를 할당하여 3을 저장하고

int num = (int)obj;

변수 사용하려고 가져오려하면 heap에 저장된걸 stack에 다시 저장하기 때문에 연산 과정이 생기기에 느려진다.

그래서 모든것을 object를 사용하는 것은 무리가 있다.

2.일반화 형식 (템플릿)

class MyList<T> //템플릿 클래스
{
	T[] arr = new T[10];
    
    public T GetItem(int i)
    {
    	return arr[i];
    }
}
static void Test<T>(T input)
{
	//템플릿 함수
}

static void Main(string[] args)
{
	MyList<int> myIntList = new MyList<int>();
    MyList<float> myIntList = new MyList<float>();
    MyList<Monster> myIntList = new MyList<Monster>();
    
    Test<int>(3);
}

템플릿은 함수나 클래스를 개별적으로 다시 만들지 않고도 각기 다른 수많은 자료형을 동작 할 수있게 해준다.

C++에서는 안되고 C#에만 되는 기능이 하나 더 있는데 템플릿에 조건을 걸어 줄 수 있다.

class MyList<T> where T : Monster
{
	T[] arr = new T[10];
}

예를 들어,
where T : struct -> T는 반드시 값형식
where T : class -> T는 반드시 참조
where T : Monster -> T는 Monster거나 상속받아야한다.
where T : new() -> T는 반드시 기본 생성자를 가지고 있어야한다.

0개의 댓글