아래내용은 한빛미디어에서 출판된 조성진님의
ASP.NET 2.0 웹프로젝트와 실전 프로그래밍 의 내용을
참고하여 글을 썼습니다.
우연히 마소에서 제네릭이라는 것에 대하여 소개를 했던 기억이 있습니다.
그땐 이게 머지? 하며 그냥 넘어갔는데.
다시 제네릭이라는것을 접하게 되었습니다.
제네릭 컬렉션
제네릭 클래스
제네릭 메서드
우선 다음과 같은 코드의 소스가 있다고 하면은
ArrayList items = new ArrayList();
items.Add("문자열");
items.Add(200);
foreach(string val in items)
Response.Write(val + "<br>");
이코딩은 두가지 문제점이 있습니다.
첫번째 문제점은 이렇게 코딩이 되어있다면 컨파일을 하는 중에는 에러가 생기지 않습니다.
하지만 실행 시에 에러가 발생합니다.
200 이라는 숫자가 ArrayList 에 들어가기 때문에
foreach 문이 실행중에 숫자를 string 형으로
변환하려고 하는중에 발생되는 에러입니다.
컴파일시에 에러가 발견되지 않고 실행을 해보고 나서야
에러가 발견된다는 것은 소프트웨어의 생산 능률을
저하시키는 요인이 될 수 있습니다.
두번째 문제점은 형식 변환으로 인한 퍼포먼스의 저하입니다.
ArrayList는 저장하는 모든 개체를 object 형식으로 변환하기 때문에
저장될때 형변환이 발생하고, 특히 int형을 object형으로 변환할 때 필요한
박싱(boxing) 처리가 수행되기 때문에 더 부담이 큽니다.
또한 다시 object 형을 string 형으로 다시 바꾸는 역변환이 발생합니다.
위 예제처럼 간단한 처리에는 표시가 나지않지만
ArrayList에 저장되는 데이터가 많아질 경우에는 반복적인 형변환과
박싱/언박싱 처리가 퍼포먼스에 치명적인 결함을 가져올 수 있습니다.
제네릭 컬렉션을 사용한 다른경우를 보면
System.Collections.Generic.List<int> values = new System.Collections.Generic.List<int>();
values.Add(100);
values.Add(200);
foreach(int val in values)
Response.Write(val.ToString() + "<br>");
System.collections.Generic 네임스페이스에 있는 List<T> 클래스는
ArrayList 클래스의 제네릭 버젼입니다.
ArrayList 클래스는 모든 형식의 데이터를 object 형식으로 저장하는 반면
List<T> 클래스는 T에 지정된 형식의 데이터를 저장합니다.
T 자리에는 모든 데이터 형식이 지정될 수 있습니다.
List<string> oVar1;
List<DataTime> oVar2;
List<char> oVar3;
List<UserDefinedType> oVar4; // UserDefineType은 사용자 정의 클래스 이름
위의 소스에서는 List<int> 라고 선언했으므로 형변환이나 박싱/언박싱이
발생되지 않습니다.
또한 만일 values.Add("텍스트") 라는 코드를 추가하면 컴파일 시간에 에러를
발견할수 있습니다.
이렇게 제네릭을 이용하면 모호한 형식에 의해 발생하는 결함들을
근본적으로 제거할 수 있습니다.
제네릭 컬렉션의 클래스들
이와같이 제네릭 메서드 나 제네릭 클래스를 정의 할수있습니다.
제네릭 메서드 또는 클래스로 코드를 작성하면 컴파일러는
각형식의 메서드 또는 클래스가 정의 된것처럼 컴파일할 겁니다.
void MethodName<T>(T parm)
{
Response.Write(parm.GetType().ToString();
}
MethodName<int>(10);
MethodName<string>("문자열")
위와 같이 되어있으면 컴파일러는 < 와 > 안에 지정한 형식과 일치하는 두종류의
메서드가 정의된 것처럼 컴파일 합니다.
void MethodName(int parm)
{
Response.Write(parm.GetType().ToString());
}
void MethodName(string parm)
{
Response.Write(parm.GetType().ToString());
}
또한 제네릭 메서드는 둘이상의 형식 매개 변수를 정의 할수있습니다.
void MethodName<T1, T2>(T1 parm1, T2 parm2)
{
...
}
그리고 제네릭 메서드는 좀더 편한 방법으로 호출할 수 있습니다.
MethodName(10, "문자열");
MethodName( "문자열", DateTime.Now);
이렇게 형식 매개 변수를 생략하고 호출하면, 메서드로 전달된 인자의 형식에 따라
컴파일러가 형식 매개 변수를 추론해서 생성합니다.
ASP.NET 2.0 웹프로젝트와 실전 프로그래밍 의 내용을
참고하여 글을 썼습니다.
우연히 마소에서 제네릭이라는 것에 대하여 소개를 했던 기억이 있습니다.
그땐 이게 머지? 하며 그냥 넘어갔는데.
다시 제네릭이라는것을 접하게 되었습니다.
제네릭 컬렉션
제네릭 클래스
제네릭 메서드
우선 다음과 같은 코드의 소스가 있다고 하면은
ArrayList items = new ArrayList();
items.Add("문자열");
items.Add(200);
foreach(string val in items)
Response.Write(val + "<br>");
이코딩은 두가지 문제점이 있습니다.
첫번째 문제점은 이렇게 코딩이 되어있다면 컨파일을 하는 중에는 에러가 생기지 않습니다.
하지만 실행 시에 에러가 발생합니다.
200 이라는 숫자가 ArrayList 에 들어가기 때문에
foreach 문이 실행중에 숫자를 string 형으로
변환하려고 하는중에 발생되는 에러입니다.
컴파일시에 에러가 발견되지 않고 실행을 해보고 나서야
에러가 발견된다는 것은 소프트웨어의 생산 능률을
저하시키는 요인이 될 수 있습니다.
두번째 문제점은 형식 변환으로 인한 퍼포먼스의 저하입니다.
ArrayList는 저장하는 모든 개체를 object 형식으로 변환하기 때문에
저장될때 형변환이 발생하고, 특히 int형을 object형으로 변환할 때 필요한
박싱(boxing) 처리가 수행되기 때문에 더 부담이 큽니다.
또한 다시 object 형을 string 형으로 다시 바꾸는 역변환이 발생합니다.
위 예제처럼 간단한 처리에는 표시가 나지않지만
ArrayList에 저장되는 데이터가 많아질 경우에는 반복적인 형변환과
박싱/언박싱 처리가 퍼포먼스에 치명적인 결함을 가져올 수 있습니다.
제네릭 컬렉션을 사용한 다른경우를 보면
System.Collections.Generic.List<int> values = new System.Collections.Generic.List<int>();
values.Add(100);
values.Add(200);
foreach(int val in values)
Response.Write(val.ToString() + "<br>");
System.collections.Generic 네임스페이스에 있는 List<T> 클래스는
ArrayList 클래스의 제네릭 버젼입니다.
ArrayList 클래스는 모든 형식의 데이터를 object 형식으로 저장하는 반면
List<T> 클래스는 T에 지정된 형식의 데이터를 저장합니다.
T 자리에는 모든 데이터 형식이 지정될 수 있습니다.
List<string> oVar1;
List<DataTime> oVar2;
List<char> oVar3;
List<UserDefinedType> oVar4; // UserDefineType은 사용자 정의 클래스 이름
위의 소스에서는 List<int> 라고 선언했으므로 형변환이나 박싱/언박싱이
발생되지 않습니다.
또한 만일 values.Add("텍스트") 라는 코드를 추가하면 컴파일 시간에 에러를
발견할수 있습니다.
이렇게 제네릭을 이용하면 모호한 형식에 의해 발생하는 결함들을
근본적으로 제거할 수 있습니다.
제네릭 컬렉션의 클래스들
.NET 1.x 컬렉션 / .NET 2.0에 추가된 제네릭 컬렉션
ArrayList / List<T>
Hashtable / Dicrionary<TKey, TValue>
SortedDictionary<TKey, TValue>
SortedList / SortedList<TKey, TValue>
Queue / Queue<T>
Stack / Stack<T>
이와같이 제네릭 메서드 나 제네릭 클래스를 정의 할수있습니다.
제네릭 메서드 또는 클래스로 코드를 작성하면 컴파일러는
각형식의 메서드 또는 클래스가 정의 된것처럼 컴파일할 겁니다.
void MethodName<T>(T parm)
{
Response.Write(parm.GetType().ToString();
}
MethodName<int>(10);
MethodName<string>("문자열")
위와 같이 되어있으면 컴파일러는 < 와 > 안에 지정한 형식과 일치하는 두종류의
메서드가 정의된 것처럼 컴파일 합니다.
void MethodName(int parm)
{
Response.Write(parm.GetType().ToString());
}
void MethodName(string parm)
{
Response.Write(parm.GetType().ToString());
}
또한 제네릭 메서드는 둘이상의 형식 매개 변수를 정의 할수있습니다.
void MethodName<T1, T2>(T1 parm1, T2 parm2)
{
...
}
그리고 제네릭 메서드는 좀더 편한 방법으로 호출할 수 있습니다.
MethodName(10, "문자열");
MethodName( "문자열", DateTime.Now);
이렇게 형식 매개 변수를 생략하고 호출하면, 메서드로 전달된 인자의 형식에 따라
컴파일러가 형식 매개 변수를 추론해서 생성합니다.