일반화 프로그래밍 #
일반화 메소드 #
- 일반화 메소드(Generic Method)
- 데이터 형식을 일반화한 메소드이다.
- 구체적인 형식대신 형식 매개변수(Type Parameter) 가 들어간다.
// 일반화 메소드. T는 형식 매개변수이다.
void CopyArr<T>(T[] source, T[] target)
{
for (int i = 0; i < source.Length; i++)
target[i] = source[i];
}
일반화 클래스 #
// 제네릭 클래스
class GenericArr<T>
{
private T[] arr = new T[3];
// 인덱서
public T this[int idx]
{
get
{
return arr[idx];
}
set
{
if (idx >= arr.Length)
Array.Resize<T>(ref arr, idx + 1);
arr[idx] = value;
}
}
}
class MainApp
{
static void Main(string[] args)
{
GenericArr<int> m = new GenericArr<int>();
for (int i = 0; i < 5; i++)
m[i] = i;
for (int i = 0; i < 5; i++)
Console.WriteLine($"{m[i]}"); // 0, 1, 2, 3, 4
}
}
형식 매개변수 제약시키기 #
- 형식 매개변수
T
는 모든 데이터 형식을 대신할 수 있다.
- 이것은
where
절을 추가함으로써 제약시킬 수 있다.
제약 |
설명 |
where T : struct |
T 는 값 형식이어야 한다. |
where T : class |
T 는 참조 형식이어야 한다. |
where T : new() |
T 는 반드시 매개변수가 없는 생성자가 있어야 한다. |
where T : 기반 클래스 이름 |
T 는 명시한 기반 클래스이거나 그의 파생 클래스여야 한다. |
where T : 인터페이스 이름 |
T 는 명시한 인터페이스를 구현해야한다. 여러 개의 인터페이스를 명시할 수도 있다. |
where T : U |
T 는 U 로부터 상속받은 클래스여야한다. |
일반화 컬렉션 #
System.Collections.Generic
네임스페이스는 다양한 일반화 컬렉션들을 담고 있다.
- 일반화 컬렉션은 박싱과 언박싱같은 형식 변환이 매번 일어나지 않기 때문에 좋다.
용도 |
제네릭 |
논-제네릭 |
인덱스 별로 엑세스 |
List<T> |
Array , ArrayList |
순서대로 액세스 |
LinkedList<T> |
|
FIFO 방식으로 사용 |
Queue<T> |
Queue |
LIFO 방식으로 사용 |
Stack<T> |
Stack |
키/값 쌍으로 저장 |
Dictionary<TKey, TValue> |
Hashtable |
추가, 삭제 시 알림 표시 |
ObservableCollection<T> |
|
정렬된 컬렉션 |
SortedList<TKey, TValue> |
SortedList |
수학 함수용 집합 |
HashSet<T> |
|
foreach를 사용할 수 있는 일반화 클래스 #
IEnumerable<T>
인터페이스를 구현하면 형식 변환 없이 일반화 클래스로 foreach
를 사용할 수 있겠다.
IEnumerator GetEnumerator()
IEnumerator<T> GetEnumerator()
bool MoveNext()
void Reset()
object Current {get;}
T Currnet {get;}
class MyList<T> : IEnumerable<T>, IEnumerator<T>
{
private T[] arr = new T[3];
private int pos = -1;
// 인덱서
public T this[int idx]
{
get
{
return arr[idx];
}
set
{
if (idx >= arr.Length)
Array.Resize<T>(ref arr, idx + 1);
arr[idx] = value;
}
}
// IEnumerator의 메소드 및 프로퍼티
object IEnumerator.Current { get { return arr[pos]; } }
public T Current { get { return arr[pos]; } }
public bool MoveNext()
{
if (pos == arr.Length - 1)
{
Reset();
return false;
}
pos++;
return (pos < arr.Length);
}
public void Reset()
{
pos = -1;
}
// IEnumerable의 메소드
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
public IEnumerator<T> GetEnumerator()
{
return this;
}
public void Dispose()
{
//...
}
}
class MainApp
{
static void Main(string[] args)
{
MyList<int> m = new MyList<int>();
for (int i = 0; i < 5; i++)
m[i] = i;
// foreach문이 가능!
foreach (int number in m)
Console.WriteLine($"{ number }"); // 0, 1, 2, 3, 4
}
}