Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

나의 지식 보관소

제네릭(일반화) / Generic 본문

프로그래밍 언어/C#

제네릭(일반화) / Generic

야식은진리다 2020. 4. 22. 03:25

제네릭은 내부에서 사용할 데이터 형식을 외부에서 결정하도록 하는 기법이다. 이런 방식을 사용하면 같은 역할을 하지만 값의 형식이 달라서 여러 개로 만들어야만 했던 클래스나 메서드들을 하나로 일반화할 수 있다.

 

제네릭 메서드

제네릭 메서드는 메서드내에서 사용할 데이터 형식을 외부에서 결정하도록 한 메서드이고, 아래와 같이 선언한다.

1
2
3
4
한정자 반환형식 메서드이름<형식매개변수> ( 매개 변수 목록 )
{
    //...
}

호출할땐 아래와 같이 사용하면 된다.

1
메서드이름<형식 매개 변수형> ( 넘겨줄 인자들 );

 

 

즉 아래와 같이 선언하고 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Program
{
    static void Main()
    {
        TestClass.test<int>(1);
    }
}
 
class TestClass
{
    static public void test<T>(T value)
    {
        Console.WriteLine($"{value.GetType()} : {value.ToString()}");
    }
}

test 메서드는 T라는 형식 매개 변수를 데이터 형식 대신 사용하고, 호출할 때 T를 어떤 형식으로 사용할지 정할 수 있다.

 

 

 

 

제네릭 클래스

제네릭 클래스는 클래스 내부에서 사용할 데이터 형식을 외부에서 결정하도록 하는 기법이다. 

1
2
3
4
class 클래스이름<형식매개변수>
{
    //...
}

사용은 다음과 같이 하면 된다.

1
클래스이름<형식매개변수형> 인스턴스이름 = new 클래스이름<형식매개변수형>();

 

 

즉 아래와 같이 선언하고 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Program
{
    static void Main()
    {
        TestClass<intstring> testClass = new TestClass<intstring>(1"Hello");
        testClass.test();
    }
}
 
class TestClass<A, B>
{
    A input1;
    B input2;
 
    public TestClass(A input1, B input2)
    {
        this.input1 = input1;
        this.input2 = input2;
    }
 
    public void test()
    {
        Console.WriteLine($"input1 : {input1.GetType()}, {input1.ToString()}");
        Console.WriteLine($"input2 : {input2.GetType()}, {input2.ToString()}");
    }
}

이번 코드에서처럼 형식 매개변수는 여러 개가 올 수 있다는 점도 기억하자.

 

 

 

 

형식 매개 변수 제약시키기

앞선 설명에서 모든 형식 매개 변수는 "모든" 데이터 형식을 대신할 수 있다. 하지만, 예를 들어, 두 데이터의 크기를 비교하는 제네릭 메서드가 있다고 가정해보자.

만일 데이터 형식이 int, double, float이거나 내부적으로 비교 연산에 어떤 대응을 할지 정해져 있는 형식이라면 문제없겠지만, 제네릭은 외부에서 데이터 형을 정할 수 있다는 점에서 메서드를 사용하는 다른 사람이, 사용할 수 없는 데이터 형식을 지정하게 되면 문제가 생긴다. 때문에 형식 매개 변수에 조건 제약을 걸 수 있다.

 

사용하는 방법은 다음과 같다.

1
2
3
4
class TestClass<T> where T : 조건
{
    //...
}

조건에는 여러 가지가 들어갈 수 있는데 다음과 같은 것들이 있다.

제약 설명
where T : struct T는 값 형식이어야 한다.
where T : class T는 참조 형식이어야 한다.
where T : new() T는 반드시 매개 변수가 없는 생성자가 있어야 한다.
where T : 기반_클래스_이름 T는 명시한 기반클래스의 파생클래스여야 한다.
where T : 인터페이스_이름 T는 명시한 인터페이스를 반드시 구현해야 한다. 인터페이스_이름에는 여러 개의 인터페이스를 명시할 수도 있다.
where T : U T는 또 다른 형식 매개 변수 U로 부터 상속받은 클래스여야 한다.

 

즉 두 데이터를 비교 연산자로 비교하는 클래스를 만들고 싶다면 다음과 같이 적어주면 된다.

1
2
3
4
class TestClass<T> where T : IComparable
{
    //...
}

IComparable을 상속한 데이터는 모두 비교 연산에 어떻게 대응할지 구현이 되어있는 형식이라는 뜻이기 때문에 위와 같은 코드가 성립한다.

'프로그래밍 언어 > C#' 카테고리의 다른 글

대리자  (0) 2020.05.05
프로세스와 스레드 / 동기화  (0) 2020.05.05
가변 배열 ( Jagged Array )  (0) 2020.04.22
무명 형식  (0) 2020.04.21
프로퍼티  (0) 2020.01.10