일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 백준 1103번 게임
- 2870번
- 코테
- 유니티
- Beakjoon
- 오브젝트 풀링
- 수학숙제
- 백준 1103번 c++
- 백준 c++ 2870번
- dfs
- 백준 1103번
- 2870번 수학숙제 c++
- 2870번 수학숙제
- 2468 c++
- 백준 17070번 c++
- 백준 17070번
- Lv.3
- 17070번
- Unity
- 백준
- 프로그래머스
- C#
- 백준 c++ 2468번
- Algorithm
- 2870번 c++
- 백준 2870번
- 플레이어 이동
- Lv2
- c++
- 코딩테스트
- Today
- Total
주녘공부일지
[C#] 제네릭 (Generic) 본문
제네릭 (Generic)
- 서로 다른 형식들에 대해 재사용할 수 있는 코드를 작성하기 위해 사용하는 메커니즘
- 형식 안정성을 높이고 캐스팅과 박싱을 줄이기 위한 수단이 됨 (일반화, 특수화)
+ 제네릭 컬렉션의 자료구조를 부분적으로 직접 구현해 예제로 삼음
https://godgjwnsgur7.tistory.com/46
1) 제네릭 형식
형식 매개변수를 선언해 사용하는 형식
- 형식 매개변수는 제네릭 형식이 실제로 사용될 때 제공되는 실제 형식을 대신할 자리를 표시하는 '자리표' 역할
ex) 제네릭 형식 Stack<T> / 형식 매개변수 T (이름은 관례적으로 T를 사용하거나 T로 시작함)
// 열린 형식 Stack<T>
public class Stack<T>
{
int position;
T[] data = new T[100];
public void Push(T obj) => data[position++] = obj;
public T Pop() => data[--position];
}
public static void Main()
{
var stack = new Stack<int>(); // 닫힌 형식 intStack 선언
stack.Push(1);
stack.Push(2);
int num = stack.Pop(); // num = 2
}
if) 만약, 제네릭 형식없이 object를 원소 형식으로 사용해 스택을 일반화 한다면?
- 모든 원소 형식에 대해 작동하도록 일반화는 가능하지만, 특정 원소 형식에 맞게 특수화되지 않음
2) 제네릭 메서드
형식 매개변수를 사용하여 선언된 메서드
ex) 같은 형식의 변수 두 개의 값을 맞바꾸는 Swap 메서드
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
public static void Main()
{
int a = 1, b = 2;
Swap(ref a, ref b);
Swap<int>(ref a, ref b); // 명시적 지정 가능
}
3) 형식 매개변수의 선언
- 클래스나 구조체, 인터페이스, 대리자, 메서드 선언에서만 도입 가능 ( 이외에는 사용만 가능 )
- default 키워드를 이용해 제네릭 형식 매개변수의 인스턴스의 기본 값을 지정 가능
-> ( 참조 : null / 값 : 모든 비트가 0인 경우의 값 으로 지정됨 )
- 여러 개의 형식 매개변수 도입 가능
- 형식 매개변수의 개수가 다를 경우 제네릭 형식 이름 & 제네릭 메서드 이름 중복 가능
ex) 위 내용에 대한 예제 모음
// 속성 Value는 형식 매개변수 T를 사용하기만 함
public struct Nullable<T>
{
public T Value { get; }
}
// 배의 인스턴스들의 값을 기본 값으로 초기화하는 메서드
public static void Zap<T>(T[] array)
{
for (int i = 0; i < array.Length; i++)
array[i] = default(T); // 기본 값으로 지정
}
// 여러 개의 형식 매개변수가 도입된 제네릭 형식
class Dictionary<TKey, TValue> { ... }
public static void Main()
{
Dictionary<int, string> myDic = new Dictionary<int, string>();
var myDic2 = new Dictionary<int, string>();
}
// 제네릭 형식 이름 & 제네릭 메서드 이름 중복가능
class A { }
class A<T> { }
class A<T1, T2> { }
4) 제네릭 제약
어떤 형식도 대입할 수 있는 형식 매개변수에 제약 조건을 지정해 제한
where T : (기반클래스명) | 기반 클래스 제약 조건 ( 파생 클래스 가능 ) |
where T : (인터페이스명) | 인터페이스 제약 조건 ( 인터페이스 구현 강제 ) |
where T : class | 참조 형식 제약 조건 |
where T : struct | 값 형식 제약 조건 ( 널 가능 형식은 제외 ) |
where T : new() | 매개변수 없는 생성자 제약 조건 ( 매개변수가 없는 공용 생성자가 있어야 함 ) |
where U : T | 형식 매개변수가 다른 매개변수와 같은 형식이거나 파생 형식이여야 함 |
ex) GenericClass<T, U>에서 T는 SomeClass이거나 SomeClass의 파생된 Interface1을 구현하는 방식이여야 하고, U는 매개변수가 없는 생성자를 제공해야 함
class SomeClass {}
interface Interface1 {}
class GenericClass<T, U> where T : SomeClass, Interface1
where U : new()
{ ... }
ex) 제네릭 형식을 파생할 경우와 형식 매개변수를 닫거나 여는 예제
class Stack<T> { ... }
class List<T> { ... }
// 형식 매개변수를 열린 형식으로 파생
class SpecialStack<T> : Stack<T> { ... }
// 형식 매개변수를 닫힌 형식으로 파생 (int)
class IntStack<int> : Stack<T> { ... }
// 파생 클래스에서 새로운 형식 매개변수 도입 (제네릭 이름 변경 가능)
class KeyedList<TElement, TKey> : List<TElement> { ... }
ex) 정적 자료 멤버는 각각 닫힌 형식마다 고유함을 나타내는 예제
class Bob<T> { public static int Count; }
public static void Main()
{
Console.WriteLine(++Bob<int>.Count); // 1
Console.WriteLine(++Bob<int>.Count); // 2
Console.WriteLine(++Bob<string>.Count); // 1
Console.WriteLine(++Bob<object>.Count); // 1
Console.WriteLine(++Bob<int>.Count); // 3
}
참고도서) C# 6.0 완벽가이드
'Programming > Definition, Etc' 카테고리의 다른 글
[C#] 대리자(delegate) vs 인터페이스(interface) (0) | 2023.11.10 |
---|---|
[C#] 대리자 (Delegate - Action, Func) (0) | 2023.11.10 |
[C#] 열거형 (enum type) (1) | 2023.10.15 |
[C#] 인터페이스 ( interface ) (0) | 2023.10.12 |
[C#] Object 형식과 박싱&언박싱 (0) | 2023.10.11 |