728x90
반응형
1. 예제
using System;
class Program {
public static void Swap(ref int a, ref int b) {
int temp = a;
a = b;
b = temp;
}
public static void Sort(int[] arr) {
int sz = arr.GetLength(0);
for(int i = 0; i < sz -1; i++) {
for(int j = i + 1; j < sz; j ++) {
if(arr[i] > arr[j])
Swap(ref arr[i], ref arr[j]);
}
}
}
static void Main() {
int[] x = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
Sort(x);
foreach(int n in x)
Console.WriteLine(n);
}
}
위의 코드는 Main의 배열 x를 오름차순으로 정렬해주는 코드이다.
Swap 같은 경우 실제 값을 바꿔야 하기에 ref 로 인자를 전달 받는다.
Sort에서 배열의 앞과 뒤를 비교해 크면 자리를 바꾸어 정렬하는 간단한 코드인데
현재 문제는 오름차순만 된다.
내림차순으로 바꾸려면 15번째 라인의 if(arr[i] > arr[j])를 if(arr[i] < arr[j])로 바꾸어야 한다.
근데 일반적으로 이러한 Sort는 라이브러리의 내부 코드일 확률이 높다.
그런데 사용자가 오름차순, 내림차순을 정하기 위해 내부 코드를 마음대로 수정하는것은 안된다.
그렇다면 사용자가 사용할 때 오름차순, 내림차순을 정해서 Sort하는게 편할 것이다.
즉, 15번 라인의 비교연산자를 >로 쓸지 <로 쓸지를 정하면 좋을 것이다.
이럴 경우 변하는 부분인 15번 라인을 함수 인자로 뽑고 시작한다.
① 공통성과 가변성의 분리
=> 변하지 않는 코드 내에 있는 변하는 코드는 분리한다.
=> 알고리즘은 변경되지 않는데, 정책을 변경하고 싶은 경우
=> 변하는 부분(정책)을 함수 인자로 변경한다 => delegate
using System;
delegate int Comparison(int arg1, int arg2);
class Program {
public static void Swap(ref int a, ref int b) {
int temp = a;
a = b;
b = temp;
}
public static void Sort(int[] arr, Comparison cmp) {
int sz = arr.GetLength(0);
for(int i = 0; i < sz -1; i++) {
for(int j = i + 1; j < sz; j ++) {
// if(arr[i] > arr[j])
if(cmp(arr[i], arr[j]) > 0)
Swap(ref arr[i], ref arr[j]);
}
}
}
static void Main() {
int[] x = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
Sort(x,
delegate(int a, int b) {return a > b ? 1 : -1; });
foreach(int n in x)
Console.WriteLine(n);
}
}
먼저 17번 라인을 인자로 뺐다.
인자는 비교에 필요한 메소드를 받아야 하므로 delegate를 만들었다.
Comparison이란 delegate는 비교를 위한 int형 인자 2개를 받고 int타입을 반환한다.
또 인자로 받은 Comparison을 사용하여 0보다 클 경우 Swap을 하도록 했다.
이제 비교하는 메소드를 만들어야 한다.
Main밖에 만들어도 되지만 이전 포스트에서 쓴 익명 메소드를 사용해 27~28번 라인과 같이 작성했다.
28번 라인에서 a > b로 할 경우 오름차순이 되고, a < b로 할 경우 내림차순이 된다.
이로써 알고리즘 자체는 변경되지 않지만
사용자가 정책을 결정해 원하는 순서로 정렬할 수 있게 되었다.
마지막으로 위의 코드를 좀 더 발전시켜보자.
using System;
delegate int Comparison<T>(T arg1, T arg2);
class Program {
public static void Swap(ref int a, ref int b) {
int temp = a;
a = b;
b = temp;
}
public static void Sort(int[] arr, Comparison<int> cmp) {
int sz = arr.GetLength(0);
for(int i = 0; i < sz -1; i++) {
for(int j = i + 1; j < sz; j ++) {
if(cmp(arr[i], arr[j]) > 0)
Swap(ref arr[i], ref arr[j]);
}
}
}
static void Main() {
int[] x = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
Sort(x,
delegate(int a, int b) {return a > b ? 1 : -1; });
foreach(int n in x)
Console.WriteLine(n);
}
}
현재 문제는 Sort가 int타입에 대해서만 가능하다는 것이였다.
하지만 delegate를 만들 때 Comparison을 Generic으로 만들어 모든 타입에 대해 가능하게 되었다.
2. 추가
위의 코드에서 Comparison과 Sort는 사실 C#에 이미 정의되어있다.
① Comparison<T>
=> 두 수를 비교하는 메소드를 담은 generc delegate
② Array 클래스
=> 배열에 적용할 수 있는 다양한 static method 제공
=> Array.Sort()
Array.Sort(x); // 오름차순
Array.Sort(x,
delegate(int a, int b) { return a < b ? 1 : -1; }
); // 내림차순
728x90
반응형
'프로그래밍 > C#' 카테고리의 다른 글
[C#] event (0) | 2020.04.08 |
---|---|
[C#] Delegate Chain (0) | 2020.04.07 |
[C#] Delegate (2) (0) | 2020.04.04 |
[C#] Delegate (1) (0) | 2020.03.30 |
[C#] 제너릭 제약 (Generic Constraint) (0) | 2020.03.27 |