Programming/C# - Window

C#/ 일반화(generic), 인덱서(indexer)k

esoog Polaris 2023. 6. 28. 11:51

# 근데 제네릭을 왜 쓰지?

 

1. 데이타 요소 타입을 확정하지 않고 이 데이타 타입 자체를 타입파라미터(Type Parameter)로 받아들이도록 클래스를 정의한다.(유연성)

2. 이렇게 정의된 클래스 즉 C# 제네릭 타입을 사용할 때는 클래스명과 함께 구체적인 데이타 타입을 함께 지정해 주게 된다.(타입안정성)

3. 이렇게 하면 일부 상이한 데이타 타입 때문에 여러 개의 클래스들을 따로 만들 필요가 없어지게 된다.(코드 재사용성)

4. C# 제네릭은 이렇게 클래스 이외에도 인터페이스나 메서드에도 적용될 수 있다. (확장성)

 

using System;
namespace CopyingArray
{
class MainApp
{
static void CopyArray<T>(T[] source, T[] target)
// <T> 은 형식 매개변수를 말하며, 매개변수 목록의 형식도 T로 대입하면,
// 일반화된 타입으로 모든 타입을 커버하여 오버라이드 한 것 처럼 사용할 수 있다.
{
for (int i = 0; i < source.Length; i++)
target[i] = source[i];
}
static void Main(string[] args)
{
int[] source = { 1, 2, 3, 4, 5 };
int[] target = new int[source.Length];
CopyArray<int>(source, target);
// 반환을 int로 사용하든
foreach (int element in target)
Console.WriteLine(element);
string[] source2 = { "하나", "둘", "셋", "넷", "다섯" };
string[] target2 = new string[source2.Length];
CopyArray<string>(source2, target2);
// string으로 사용하든 모두 가능하다.
foreach (string element in target2)
Console.WriteLine(element);
}
}
}
--------------------------------------------------------------------
using System;
namespace Generic
{
class MyList<T>
// 일반화 클래스는 클래스명<T> 형식 매개변수를 사용하고
{
private T[] array;
// 사용할 배열 필드는 T 형식으로 선언.
public MyList()
{
array = new T[3];
// 생성자에서 배열 객체를 먼저 생성한다.
// 기본 용량을 지정해서 생성.
}
public T this[int index]
// T 형식으로 인덱서를 만드는데, 기본 인덱서 형식은
// public this[int index]{get; set;} 형태로
// 프로퍼티를 사용하는 것과 동일하다.
{
get
{
return array[index];
}
set
{
if (index >= array.Length)
// 배열 용량을 초과해서 값이 들어온다면,
// 인덱스 증가 구현
{
Array.Resize<T>(ref array, index + 1);
Console.WriteLine($"Array Resized : {array.Length}");
}
array[index] = value;
}
}
public int Length
{
get { return array.Length; }
}
}
class MainApp
{
static void Main(string[] args)
{
MyList<string> str_list = new MyList<string>();
// 객체를 만들었는데, 객체를 바로 순회가능한 객체로 사용하기 위해
// 위에서 인덱서 사용.
str_list[0] = "abc";
str_list[1] = "def";
str_list[2] = "ghi";
str_list[3] = "jkl";
str_list[4] = "mno";
for (int i = 0; i < str_list.Length; i++)
Console.WriteLine(str_list[i]);
Console.WriteLine();
MyList<int> int_list = new MyList<int>();
int_list[0] = 0;
int_list[1] = 1;
int_list[2] = 2;
int_list[3] = 3;
int_list[4] = 4;
for (int i = 0; i < int_list.Length; i++)
Console.WriteLine(int_list[i]);
}
}
}
------------------------------------------------------------------
using System;
namespace ConstraintsOnTypeParameters
{
class StructArray<T> where T : struct
// where T : struct 은 값 형식으로 일반화 클래스를 제약
{
public T[] Array{ get;set;}
public StructArray(int size)
{
Array = new T[size];
}
}
class RefArray<T> where T : class
// where T : class 은 참조 형식으로 일반화 클래스를 제약
{
public T[] Array{ get;set;}
public RefArray(int size)
{
Array = new T[size];
}
}
class Base { }
class Derived : Base { }
class BaseArray<U> where U : Base
{
public U[] Array{ get;set;}
public BaseArray(int size)
{
Array = new U[size];
}
public void CopyyArray<T>(T[] Target) where T : U
{
Target.CopyTo(Array, 0);
}
}
class MainApp
{
public static T CreateInstance<T>() where T : new()
// where T : new() 은 기본 생성자를 가진 클래스 객체 형식으로 일반화 클래스를 제약
{
return new T();
}
static void Main(string[] args)
{
StructArray<int> a = new StructArray<int>(3);
a.Array[0] = 0;
a.Array[1] = 1;
a.Array[2] = 2;
RefArray<StructArray<double>> b = new RefArray<StructArray<double>>(3);
b.Array[0] = new StructArray<double>(5);
b.Array[1] = new StructArray<double>(10);
b.Array[2] = new StructArray<double>(1005);
BaseArray<Base> c = new BaseArray<Base>(3);
c.Array[0] = new Base();
c.Array[1] = new Derived();
c.Array[2] = CreateInstance<Base>();
BaseArray<Derived> d = new BaseArray<Derived>(3);
d.Array[0] = new Derived(); // Base 형식은 여기에 할당 할 수 없다.
d.Array[1] = CreateInstance<Derived>();
d.Array[2] = CreateInstance<Derived>();
BaseArray<Derived> e = new BaseArray<Derived>(3);
e.CopyyArray<Derived>(d.Array);
}
}
}
view raw MainApp.cs hosted with ❤ by GitHub

 

 

 

 

 

# 이해를 위한 추가 예제 코드

*System.Collections.Generic 네임스페이스에 있는 모든 자료구조 관련 클래스들은 제네릭 타입이다.

컬렉션에서 많이 사용되는 것으로 알면 편하다.

 

List<string> nameList = new List<string>();
nameList.Add("홍길동");
nameList.Add("이태백");

Dictionary<string, int> dic = new Dictionary<string, int>();
dic["길동"] = 100;
dic["태백"] = 90;

 

반응형