03
29

중요 개념 제네릭

 

 

코딩하다가 Getcomponent<T>(); 이런식으로 제네릭을 많이 보는데 맨날 개념을 까먹는다.

이런걸 매일 보는데도 헷갈린다.

이번에 간단하게 개념을 정리해보자.


#1 제네릭(Generic)이란?

 

제네릭(Generic)메서드(함수)나 클래스를 작성할 때 데이터 형식(Type)을 지정하지 않는다.

그렇기에 코드로 작성한 후, 실제 사용하는 시점에서 데이터 형식을 지정할 수 있도록 하는 기능이다. 

제네릭은 재사용성이 높고 컴파일 시점에서 타입 체크를 하기 때문에 안정적이다.

덕분에 제네릭을 쓰면 코드의 가독성과 유지보수성을 향상시킬 수 있다.

제네릭이 생긴게 <T> 이렇게 T에다가 데이터 타입을 암거나 넣을 수 있다.

데이터 타입은 말 그대로 자료형(Data Type)이다.

아래와 같은 자료형들을 얘기한다.

 

값 형식: int, float, double, bool, struct 등
참조 형식: string, object, class 등
사용자 정의 형식: enum, delegate, interface, struct 등

 

이것들 외에도 그냥 자료형이면 인식이 된다.

이제 제네릭 메서드클래스를 보면서 이해해보자.

 

1. 제네릭 메서드(함수)

 

우선 제네릭으로 함수 작성하는 방법을 보자.

T Generic<T>(T a) 로 선언하고 

public T Generic<T>(T a)
{
    return a;
}

 

사용할 때 T(Type)에 해당하는 타입에 int를 넣는다면 나머지 Tint로 정해진다.

 

예를 들어, 위의 제네릭 함수는 return a;Type int로 반환하고 싶다면

제네릭 함수를 선언할 때 Generic<T>T에다가 int를 넣으면 된다.

그러면 뒤에 따라오는 매개변수 a, b도 int로 인식이 되는걸 볼 수 있다.

var num은 말그대로 int말고 다른 타입이 와도 인식하기 위한 거니 int num이랑 똑같다.

 

실제로도 int 대신 Transform 넣으면 리턴 값도 Transform이여야하는 것을 볼 수 있다.

 

2. ref 키워드

 

다른 곳에서 자료를 찾다보니 제네릭 메서드에 ref 키워드를 항상 쓰는 느낌이다.

ref 키워드 메서드(함수)의 인수로 전달되는 값의 참조를 전달하기 위해 사용한다.

일반적으로 값형식인 변수의 값을 변경하거나 외부에게 객체의 참조를 전달하는 식으로 사용한다.

그래서 제네릭을 사용할 때 ref 키워드가 무조건 필요한건 아니다.

 

사용방법은 간단하다.

public T Generic<T>(ref T a)
{
    return a;
}

위의 제네릭 메서드랑 똑같이 하고 매개변수 부분에 ref 키워드 넣어주면된다.

 

3. 제네릭 클래스

 

사실 기본적으로 제네릭 하면 제네릭 클래스를 더 많이 볼 수 있다.

제네릭 클래스의 기본적인 형태는 다음과 같다.

접근제한자 class 클래스이름<T>

그리고 기본적인 선언 형태는 다음과 같다. (클래스에 특별한게 없다면)

클래스이름 <T> genericClass = new 클래스이름<T>();

근데 오른쪽에서 new 클래스이름 <T>(); 여기에 괄호()가 있다. 이건 타입 매개변수(T)다.

이는 생성자제네릭 클래스매개변수로 전달 가능하다. 예제를 보자.

 

public class GenericClass<T>
{
    private T data;

    public GenericClass(T data)
    {
        this.data = data;
    }

    public T GetData()
    {
        return data;
    }
}

private의 멤버 변수 하나 선언하고 생성자에서 매개변수로 입력받아 저장되게 만들었다.

이제 선언하고 우리가 원하는 자료형을 넣어서 사용해보자.

// GenericClass를 사용하여 int 형식의 데이터 저장하기
GenericClass<int> intClass = new GenericClass<int>(1);
Debug.Log(intClass.GetData()); // 1 출력

// GenericClass를 사용하여 string 형식의 데이터 저장하기
GenericClass<string> stringClass = new GenericClass<string>("hello");
Debug.Log(stringClass.GetData()); // "hello" 출력

 

보다시피 <T>에 해당하는 우리가 원하는 자료형을 넣은 뒤 괄호 사이에 데이터를 저장했다.

이런식으로 타입 매개 변수(T)의 응용이 가능하다.

 

4. where 키워드, 제약조건이란?

이제 또 보이는게 where 키워드인데, 이건 타입 매개 변수(T)만족해야 할 조건을 명시할 수 있다.

모양은 대충 이렇게 생겼다.


접근제한자 class 클래스이름 where T : 제약조건

public class GenericClass<T> where T : new()
{
}

제약 조건에는 new() 말고도 다양하게 올 수 있다.

 

where T : struct는 값 타입인 형식에 대한 제약 조건이다.
where T : class는 참조 타입인 형식에 대한 제약 조건이다.
where T : new()는 매개 변수가 없는 기본 생성자를 가지는 형식에 대한 제약 조건이다.
where T : ParentClass는 파생된 형식에 대한 제약 조건이다. 무조건 ParentClass를 상속해야한다.
where T : ISomeInterface는 ISomeInterface 인터페이스를 구현하는 형식에 대한 제약 조건이다.
where T : struct, ISomeInterface는 값 타입 형식 + 인터페이스 형식에 대한 제약 조건이다.

암튼 이런식으로 제한이 가능하다.

 

COMMENT