제네릭 클래스는 C++ 로 따지면 template 이다.
Nullble은 private int? a; 이렇게 선언하면 변수 a 의 자료형이 int 일 수도 null 일 수도 있다는 의미.
IEnumerator를 써서 GetEnumerator라는 함수를 오버라이딩 하면 해당 클래스가 Iterable 하게 된다.
- Iterable이라면 "foreach (int i in list)" 같이 사용 할 수 있다.
https://learn.microsoft.com/ko-kr/dotnet/csharp/fundamentals/types/generics
제네릭 클래스 및 메서드 - C#
제네릭에 대해 알아봅니다. 제네릭 형식은 코드 재사용, 형식 안전성 및 성능을 최대화하며 일반적으로 컬렉션 클래스를 만드는 데 사용됩니다.
learn.microsoft.com
심플예시
namespace practice;
using System;
// Declare the generic class.
public class GenericList<T>
{
public void Add(T input) { }
}
class Program
{
private class ExampleClass { }
static void Main()
{
// Declare a list of type int.
GenericList<int> list1 = new GenericList<int>();
list1.Add(1);
// Declare a list of type string.
GenericList<string> list2 = new GenericList<string>();
list2.Add("");
// Declare a list of type ExampleClass.
GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
list3.Add(new ExampleClass());
}
}
Linked List 을 구현 코드
+ Nullable(?) + IEnumerator
namespace practice;
using System;
/* Linked List 을 직접 구현하는 코드 */
public class GenericList<T>
{
// Linked List 내부에서 다룰 Node class 타입 선언
private class Node
{
private Node? next; // 다음 Node instance 를 담을 변수
// ? 의미 : next 변수의 타입이 Node 일수도 null일 수 도 있다.
// ( 정식 표현은 Nullable 이라고 함 )
private T data; // 실 데이터를 넣을 변수
public Node(T t) // GenericList 클래스의 Node 클래스의 생성자
{
next = null; // 마지막 객체일 시, null 값
data = t; //
}
public Node? Next // Next 함수 getter setter
{ // getter : var a = ins.Next;
get { return next; } // setter : ins.Next = 33;
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node? head; // 다음 Node instance 를 담을 변수
public T pop_left() // 가장 왼편의 Linked List pop
{
if (head == null)
{
throw new InvalidOperationException("This list is empty.");
}
T res = head.Data;
head = head.Next;
return res;
}
public T get_left() // // 가장 왼편의 Linked List getter
{
if (head == null)
{
throw new InvalidOperationException("This list is empty.");
}
return head.Data;
}
public GenericList() // this class의 생성자
{ // 생성자 인자가 없으면 클래스의 디폴트 생성자를 오버라이딩하는 것
head = null;
}
public void AddHead(T t)
{ // Linked List 구조를 만드는 전신 코드
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{ /* foreach (int i in list) 같은 기능을 사용하려면
Iterable 해야되는데 그걸 구현 해주는 부분
정확히는 IEnumerable 인터페이스의 GetEnumerator 함수를 오버라이딩해주는 작업
*/
Node? current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
class Program
{
static void Main()
{
GenericList<int> list = new GenericList<int>();
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// var a = list.get_list_once(); // 이전 코드
// 수정된 메서드 호출
System.Console.WriteLine($" pop res : {list.pop_left()} "); // 출력값 : pop res : 9
System.Console.WriteLine($" get res : {list.get_left()} "); // 출력값 : get res : 8
System.Console.WriteLine($" pop res : {list.pop_left()} "); // 출력값 : pop res : 8
foreach (int i in list)
{
System.Console.Write(i + " "); // 출력값 : 7 6 5 4 3 2 1 0
}
System.Console.WriteLine("\nDone"); // 출력값 : Done
}
}
'언어 정리 > C# 개념 및 lib' 카테고리의 다른 글
예외처리 (0) | 2024.01.24 |
---|---|
익명 형식 vs 딕셔너리, 가변인자 (0) | 2024.01.24 |
vscode with c# in wsl (1) | 2024.01.23 |
참조자, static method, 오버라이딩, 오버로드 (1) | 2024.01.09 |
구조체, 인터페이스, 열거형(enum), 튜플, 네임드튜플, 딕셔너리, Nullable (0) | 2024.01.09 |
댓글