외로운 Nova의 작업실
c# 언어 공부 - 7(일반화 프로그래밍) 본문
안녕하세요. 오늘은 저번시간에이어 c#의 일반화 프로그래밍과 예외처리를 배워보도록 하겠습니다.
<일반화 프로그래밍>
일반화 프로그래밍은 객체들의 공통점을 찾아서 일반화 하는 프로그래밍을 말합니다.
예를들어 int[], string[], double[] 객체들의 공통점은 배열이라는 것입니다.
일반화 프로그래밍은 다음과 같은 상황일때 유용합니다.
1.배열을 copy하는 copyarray 객체를 만들었습니다.
class CopyArray
{
}
2. int[]배열을 copy하는 메소드를 만들었습니다.
class CopyArray
{
public void Copyint(int[] a, int[] b)
{
for(int i = 0; i < a.Length; i++)
{
a[i] = b[i];
}
}
}
3.쓰다보니 string[]배열을 copy하는 메소드가 필요합니다.
4.string[]배열을 copy하는 메소드를 만들었습니다.
public void Copyint(int[] a, int[] b)
{
for(int i = 0; i < a.Length; i++)
{
a[i] = b[i];
}
}
public void Copysting(string[] a, string[] b)
{
for (int i = 0; i < a.Length; i++)
{
a[i] = b[i];
}
}
5.쓰다보니 double[] 배열을 copy하는 메소드가 필요합니다.
.
.
.
이런식으로 31가지의 copy하는 메소드를 만들게되었습니다.
위와같은 방법으로 메소드를 다 구현할 수 있지만.
일반화 프로그래밍을 사용하면 1가지 메소드만 구현하면 됩니다.
위 31개의 메소드들을 1개의 일반화 메소드로 바꿔보겠습니다.
class CopyArray
{
public void Copy<T>( T[] a, T[] b) //T는 형식 매개변수
{
for(int i = 0; i < a.Length; i++)
{
a[i] = b[i];
}
}
}
T는 형식매개변수로 int, string, double 등이 들어갈 수 있습니다.
그럼 실제로 사용도 해보겠습니다.
using System;
namespace StudyCSharp
{
class MainApp
{
static void Main(string[] args)
{
int[] a = { 1, 2, 3 };
int[] b = new int[3];
double[] c = {1.2, 1.3, 1.4};
double[] d = new double[3];
CopyArray copy = new CopyArray();
copy.Copy(a, b); //int형 메소드
Console.WriteLine($"{b[0]}, {b[1]}, {b[2]}");
copy.Copy(c, d); //double향 메소드
Console.WriteLine($"{d[0]}, {d[1]}, {d[2]}");
}
class CopyArray
{
public void Copy<T>( T[] a, T[] b) //T는 형식 매개변수
{
for(int i = 0; i < a.Length; i++)
{
b[i] = a[i];
}
}
}
}
}
<일반화 클래스>
클래스를 만들때도 int에 관련된 클래스를 만들었더니 string 클래스가 필요해서 string 클래스를 만들고 또 이렇게하다보니 31가지 클래스를 만드는 경우에도 일반화 할 수 있습니다.
먼저 일반화 클래스가 아닌 경우의 코드입니다.
class IntValue
{
public int value;
}
class StringValue
{
public string value;
}
.
.
.
.
위를 일반화 클래스로 변경해보겠습니다.
class anyValue<T>
{
public T value;
}
이런식으로 또 T 형식 매개변수를 이용하여 사용할 수 있습니다.
T에는 int, stirng, double등이 들어가면 int가 들어갈경우 int형 변수 value가 만들어집니다.
그럼 일반화 클래스를 한번 사용해보겠습니다.
using System;
namespace StudyCSharp
{
class MainApp
{
static void Main(string[] args)
{
anyValue<int> val = new anyValue<int>(); //int형 일반화 클래스 선언
val.value = 3;
Console.WriteLine(val.value);
anyValue<stirng> val2 = new anyValue<string>(); //string형 일반화 클래스 선언
val.value = "hello";
Console.WriteLine(val2.value);
}
class anyValue<T>
{
public T value;
}
}
}
<형식 매개변수 제약시키기>
일반적으로 형식 매개변수에는 모든 형식이 들어갈 수 있습니다.
하지만 종종 특정 조건을 갖춘 형식에만 대응하는 형식 매개변수가 필요할 때도 있습니다.
예를 들어, T 형식매개 변수에는 정수형만 들어가게하는 것처럼 말입니다.
그러면 string은 못들어가겠죠 정수형이 아니니까요.
이처럼 형식 매개변수를 제약할때의 방법을 알아보도록 하겠습니다.
형식 매개변수를 제약할때는 where 절을 쓰면됩니다.
예를 들어 매개변수를 값 형식 매개변수만 가능하게 하려면 아래와 같은 코드로 제약 할 수 있습니다.
class anyValue<T> where T : struct //where절로 형식 매개변수 T에 값 데이터형식만 가능하게함
{
public T value;
}
그럼 where 절에 쓸수 있는 제약조건을 정리해보도록 하겠습니다.
where T : struct | T는 값 형식만 가능합니다. |
where T : class | T는 참조 형식만 가능합니다. |
where T : new() | T는 반드시 매개변수가 없는 생성자가 있어야합니다. |
where T : 기반 클래스 이름 | T는 명시한 기반 클래스의 파생 클래스여야합니다. |
where T : 인터페이스 이름 | T는 명시한 인터페이스를 구현해야합니다. |
where T : U | T는 또 다른 형식 매개변수 U로부터 상속받은 클래스여야합니다. |
new() 까지 한번 예제를 써보도록 하겠습니다.
먼저 struct는 위에 있으니 넘어가도록 하겠습니다.
using System;
namespace StudyCSharp
{
class MainApp
{
static void Main(string[] args)
{
anyValue<int[]> val = new anyValue<int[]>(); //배열은 참조형식으로 가능합니다.
val.value[0] = 1;
Console.WriteLine(val.value);
}
class anyValue<T> where T : class //참조형식 데이터만 가능합니다.
{
public T value;
}
}
}
using System;
namespace StudyCSharp
{
class MainApp
{
static void Main(string[] args)
{
anyValue<int> val = new anyValue<int>(); //int형식은 생성자가 있습니다.
val.value = 1;
Console.WriteLine(val.value);
}
class anyValue<T> where T : new() //생성자가 있는 것만 가능합니다
{
public T value = new T(); //생성자가 있기에 이렇게 쓸 수 있습니다.
}
}
}
<일반화컬렉션>
저번시간에 배웠던 컬렉션에도 일반화 프로그래밍을 적용할 수 있습니다.
ArrayList는 List<T>로 사용할 수 있습니다.
Queue는 Queue<T>로 사용할 수 있습니다.
Stack은 Stack<T>로 사용할 수 있습니다.
HashTable은 Dictionary<TKey, TValue>로 사용할 수 있습니다.
각 자료형에는 T에서 한정하는 객체만 넣을 수 있습니다.
아래는 선언 예제입니다.
using System;
namespace StudyCSharp
{
class MainApp
{
static void Main(string[] args)
{
List<int> list = new List<int>(); //int형만 가능한 리스트 선언
Queue<int> queue = new Queue<int>(); //int형만 가능한 queue 선언
Stack<int> stack = new Stack<int>(); //int형만 가능한 stack선언
Dictionary<int,int> dic = new Dictionary<int,int>();//int형만 가능한 HashTable선언
}
}
}
<foreach를 사용할 수 있는 일반화 클래스>
저번에 인덱서를 사용하면 클래스를 배열처럼 사용 할 수 있다고 공부했습니다.
그때 foreach를 사용하려면 IEnumberable인터페이스와 IEnumerator인터페이스를 상속해야한다고 배웠죠.
일반화 클래스도 그 둘을 상속하게되면 foreach문이 가능하지만, 형식변환이 계속 이뤄지면서 오버로드가 일어납니다.
이를 위해 c#개발자들은 일반화 클래스는 IEnumerable<T>와 IEnumerator<T>를 상속받는다면 foreach문을 사용가능하게 만들었습니다.
그럼 IEnumerable와 IEnumerator 인터페이스의 만들어야할 메소드와 프로퍼티를 알아보겠습니다.
IEnumerator IEnumerable.GetEnumerator() | IEnumerator 형식의 객체를 반환 |
IEnumerator<T> GetEnumertor() | IEnumerator<T> 형식의 객체를 반환 |
boolean MoveNext() | 다음요소로 이동합니다. 이동이성공한경우엔 true 아닌경우엔 false를 반환합니다. |
void Reset() | 컬렉션 첫번쨰 위치의 앞으로 이동합니다. |
Objcet IEnumerator.Current{get:} | 컬렉션의 현재 요소를 반환합니다. |
T Current{get:} | 컬렉션의 현재요소를 반환합니다. |
위와 인덱서를 활용해서 foreach문을 사용할 수 있는 배열 일반화 클래스를 만들어보겠습니다.
using System.Collections;
using System.Collections.Generic;
위 두개를 꼭 써줘야합니다.
using System;
using System.Collections;
using System.Collections.Generic;
namespace StudyCSharp
{
class MainApp
{
static void Main(string[] args)
{
}
class MyList<T> : IEnumerable<T>, IEnumerator<T>
{
private T[] array;
int position = -1; //첫번째 배열 0의 앞 -1을 할당
public MyList() //생성자메소드
{
array = new T[3];
}
public T this[int index] //인덱서 메소드
{
get
{
return array[index];
}
set
{
array[index] = value;
}
}
public IEnumerator<T> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
public T Current
{
get
{
return array[position];
}
}
object IEnumerator.Current
{
get
{
return array[position];
}
}
public bool MoveNext()
{
if(position == array.Length-1)
{
Reset();
return false;
}
position++;
return (true);
}
public void Reset()
{
position = -1;
}
public void Dispose()
{
}
}
}
}
위와같이 코드를 짜면 MyList는 foreach문을 사용할 수 있는 일반화 배열 클래스가 됩니다.
다음시간에는 예외처리에 대해서 배워보도록 하겠습니다.
'Programming > C#' 카테고리의 다른 글
c# 언어 공부 - 9(대리자와 이벤트) (0) | 2022.05.10 |
---|---|
c# 언어 공부 - 8(예외 처리) (0) | 2022.05.07 |
c# 언어 공부 - 6(배열, 가변배열, 컬렉션, 인덱서) (0) | 2022.05.04 |
c# 언어 공부 - 5(인터페이스,추상클래스,프로퍼티) (0) | 2022.05.03 |
c# 언어 공부 - 4(상속,오버라이딩, 중첩클래스, 분할클래스, 구조체) (0) | 2022.05.02 |