Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷! Ver 2.0~

.NET은 순식간(?)에 버전업 되었습니다. 이는 신기술의 탄생도 동반했습니다 .NET 2.0 , .NET 3.0, .NET 3.5 등 새로운 기능 및 확장된 기능에 대해 다룹니다

[Generics] Generics(지네릭) 기본

작성자 : 박종명
최초 작성일 : 2008-05-13 (화요일)
최종 수정일 : 2008-05-13 (화요일)
조회 수 : 3731

* Generics

 

닷넷 프레임웍 2.0 은 그 주버전에 변경될 만큼 많은 이전 버전에 비해 많은 변화와 향상을 이루었다.

이번 아티클에서는 닷넷 프레임 2.0에서도 성능의 향상과 형변환 안정성을 가져다 준 언어적인
특징인 Generics
에 대해서 알아보자

 

 

1. legacy

 

일단 Generics 의 개념을 살펴보기 이전에 닷넷 프레임웍 1.x 기반의 언어 환경을 살펴봄으로써 Generics
이 등장하게 된 배경을 살펴보자.

일반적으로 여러 연관된 값들을 하나의 자료구조에 저장하기 위해 사용하는 것이 바로 배열이다.

배열은 동일한 타입의 값들을 하나의 (배열) 변수에 인덱스를 부여하여 저장하는 자료 구조이다.

또한 배열은 처음 생성할 때 그 크기를 명시해야만 한다.

 

int[] i = new int[2];

i[0] = 0;

i[1] = 1

크기가 2 integer 배열을 선언한 뒤 0,1 인덱스에 값을 대입하였다.

그런데 여기서 값을 하나 더 추가하기 위해서는 어떻게 해야 할까???

i 라는 배열은 이미 그 크기가 2로 고정되어 크기를 재 조정할 수가 없다.

그렇다고 해서 I = new int[3] 으로 새로 생성한다면 이전 데이터는 모두 사라진다.

물론 방법이 없는 것은 아니다. 배열 복사를 이용하면 된다.

 

static void Main(string[] args)

{

            int[] i = new int[2];

            i[0] = 0;

            i[1] = 1;

            WriteLine(i);

 

            int[] j = new int[3];

            i.CopyTo(j,0);

            j[2] = 2;

            WriteLine(j);          

}

static void WriteLine(int[] i)

{

            foreach (int value in i)

{

                Console.WriteLine(value.ToString());

}

            Console.WriteLine("=======================");

}

 

배열에 값을 하나 더 추가하기 위한 요구사항은 만족되었지만 결국 배열의 복사를 통한 새로운 배열을 만드는 것이다. 이렇듯 배열은 아래과 같은 단점을 가지고 있다.

 

= 배열의 단점 =

a.     크기가 고정되어 있다.

b.     동일한 타입의 데이터만 저장할 수 있다.

 

이런 배열의 단점을 극복하기 위해 일반적으로 많이 사용되는 자료구조가 바로 ArrayList 이다.

닷넷 프레임웍의 대표적인 컬렉션 개체로써 실행시 동적으로 크기가 조절되며 여러 가지 데이터 타입을 저장할 수 있도록 한다.

 

아래는 ArrayList Add 메서드의 시그너쳐 이다.

public virtual int Add (Object value)

 

모든 데이터 타입이 상속받는 Object 를 매개변수로 받음으로써 저장되는 타입의 제약이 없는 것이다.

 

class Program

    {

        static void Main(string[] args)

        {

            ArrayList al = new ArrayList(2);

            al.Add(1);

            al.Add("하하");

            al.Add(new Program());

            WriteLine(al);           

           

        }

 

        static void WriteLine(ArrayList a)

        {

            foreach (object value in a)

            {

                Console.WriteLine(value.ToString());

            }           

        }

    }

 

위 예를 보면 초기의 크기를 2로 설정을 했더라도 데이터를 더 많이 추가할 수 있다.(자동으로 크기가 늘어난다) 또한 예에서는 하나의 ArrayList 에 각기 다른 데이터 타입을 저장하고 있다. 이렇듯 ArrayList 는 편한 프로그래밍 환경을 제공해 준다.

 

그러나 이런 ArrayList 가 주는 장점은 따지고 보면 결국 만만찮은 비용이 지불한 셈이 되는 것이다.

Add 메서드의 시그너쳐을 보면 매개변수 타입이 Object 였다.

결국 Add 메서드를 통해 전달되는 매개변수는 Object 로 형변환 되거나 박싱이 일어나게 되는 것이다.



ILDASM 으로 살펴본 위 어셈블리는 위 그림처럼 Boxing 이 일어남을 알수 있다.

참고로 박싱과 언박싱의에 대한 자세한 글은 다음 링크를 따라가기 바란다.

Boxing & UnBoxing (박싱&언박싱) 바로가기

 

결국 위의 예에서는 한번의 박싱과 두번의 Up Casting 가 발생한 것이다.

al.Add(1);              ß Boxing

al.Add("하하");         ß Up Casting(string 객체에서 Object로의 상위 캐스팅)

al.Add(new Program());  ß Up Casting(Program 객체에서 Object로의 상위 캐스팅)

 

반대로 이 ArrayList 에서 값을 꺼집어 낼때는 언박싱 또는 Down Casting 가 일어난다.

 

 

= 컬렉션의 단점 =

a.     Object 로 변화하기 위해 다음과 같은 과정을 거친다.

값 타입 : Boxing , UnBoxing

참조 타입 : Up Casting , Down Casting

b.     저장된 데이터를 가져올 때 형식 변환(형 변환)을 명확히 해야 한다.
부적절한 형식변환을 미리(컴파일시) 알수 없다. 실행시 오류를 발생한다.

 

 

 

2. Generics 개요

 

앞서 살펴본바와 같이 배열과 컬렉션의 단점을 피하고 장점만을 가지기 위해 설계된 개념이 바로 Generics 이다.  결국 배열이 가지는 단점을 극복하기 위해 컬렉션을 사용하고 컬렉션을 사용함으로써 발생할 수 있는 성능저하와 형식 불안정성의 단점들을 또 다시 극복하기 위해 새롭게 추가된 언어적인 특징이 Generics 인 것이다.

 

Generics 는 다음과 같은 특징을 가진다.

a.     배열처럼 명확한 타입이 미리 지정되어 타입 불일치를 사전(컴파일시)에 예방할 수 있다. 즉 형식 안정성을 보장 받는다.

b.     타입이 명확히 지정되었기 때문에 Boxing(UnBoxing) , Up Casting(Down Casting) 가 발생하지 않는다. 곧 성능을 저해하는 요소가 없다.

 

 

 

3. Generics Demo

 

static void Main(string[] args)

{           

            List<int> l = new List<int>();

            l.Add(1);

            l.Add(2);

            WriteLine(l);           

}

 

static void WriteLine(System.Collections.Generic.List<int> a)

{

            foreach (object value in a)

            {

                Console.WriteLine(value.ToString());

            }           

}


위 예제를 보면 System.Collections.Generic 네임스페이스의 List<T> 컬렉션 개체를 통해 미리
형식을 지정해 놓고 사용하는 것을 알수 있다.



형식이 미리 정의되었기 때문에 Boxing 이 일어나지 않았다.

 

결국 컬렉션을 사용하여 배열의 한계를 극복하면서도 이전 환경에서 처럼 Boxing(UnBoxing),

Up Casting(Down Casting) 를 발생하지 않음으로써 성능의 향상을 이룰수 있으며

미리 데이터 타입이 지정되어 다른 데이터 타입이 저장되는 것을 미리(컴파일 시에) 알 수 있도록 해준다.

이것이 바로 Generics 인 것이다.




이름
비밀번호
홈페이지
XG <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요