728x90
반응형
1. 핵심 정리
using System;
class Point {
private int x;
private int y;
public Point(int xPos = 0, int yPos = 0) {
x = xPos;
y = yPos;
}
}
class Program {
static void Main() {
Point pt = new Point(1, 1);
// Point pt = new Point(1, 1.2);
}
}
위와 같은 코드가 있고 사용자들은 Point 객체를 만들어 사용하고 있는데
여기서 사용자가 Point pt = new Point(1, 1); 이 아닌
Point pt = new Point(1, 1.2); 와 같이 실수도 보내고 싶다라고 한다면
멤버를 double로 만들면 되긴 한다.
하지만 사용자가 다시 정수만을 사용한다면 문제는 없지만 성능이 조금 떨어지게 된다.
그렇다면 성능과 효율을 고려해서 double과 int를 정하면 되는데
타입을 만드는 사람이 정하지 않고 쓰는 사람이 정하면 어떨까?
정수만을 쓸 경우 int로 하고 실수를 쓸 경우 double을 쓰면 될 것이다.
C++에서는 이럴경우 template<type name> 이런걸 적어야 하는데
C#의 Generic은 표기법이 더욱 간단하다.
using System;
class Point<T> {
private T x;
private T y;
public Point(T xPos = 0, T yPos = 0) {
x = xPos;
y = yPos;
}
}
class Program {
static void Main() {
Point pt = new Point(1, 1);
}
}
위와 같은 형태이다.
위에서 T대신 다른 문자를 넣어도 상관없지만 관례상 T나 G를 많이 쓴다.
위의 코드에서 7번째 라인의 코드가 에러가 난다.
이제 생성자가 인자로 int타입을 받는게 아니라 임의의 타입을 받기 때문에 0으로 초기화 할 수 없다.
이 땐, 아래와 같이 바꿔주면 된다.
using System;
class Point<T> {
private T x;
private T y;
public Point(T xPos = default(T), T yPos = default(T)) {
x = xPos;
y = yPos;
}
}
class Program {
static void Main() {
Point pt = new Point(1, 1);
}
}
마지막으로 어떤 타입으로 사용한다는 것인지 모르기 때문에 사용할 때도 수정해야 한다.
using System;
class Point<T> {
private T x;
private T y;
public Point(T xPos = default(T), T yPos = default(T)) {
x = xPos;
y = yPos;
}
}
class Program {
static void Main() {
Point<int> pt = new Point<int>(1, 1);
Point<double> pt2 = new Point<double>(1.1, 1.2);
}
}
위의 형태가 클래스 제너릭의 기본 모양이다.
① 다양한 Collection 클래스(List, LinkedList 등)가 Generic으로 제공됨.
=> namespace추가 필요 (using System.Collections.Generic;)
2. Generic Method
using System;
class Program {
public static int Foo1(int a) {
return a;
}
static void Main() {
int n = Foo1(5);
}
}
위에서 클래스를 제너릭으로 만드는 법에 대해 봤다면
메소드도 제너릭으로 만들 수가 있다.
방법은 동일하다 함수명 뒤에 <T>를 붙이고 타입네임 대신 T를 넣으면 된다.
using System;
class Program {
public static T Foo1<T>(T a) {
return a;
}
static void Main() {
int n = Foo1(5);
int n2 = Foo1<int>(3);
double n3 = Foo1<double>(3.14);
int n4 = Foo1(3);
double n5 = Foo1(3.14);
}
}
제너릭으로 만든 메소드이지만 타입을 지정안해주면 인자의 타입을 보고 컴파일러가 결정한다.
혹 Foo1메소드를 사용하고 어떤 타입으로 결정되었는지 알고 싶다면
GetType() 메소드를 통해 알 수 있다.
using System;
class Program {
public static T Foo1<T>(T a) {
Type t = a.GetType();
Console.WriteLine(t.FullName);
return a;
}
static void Main() {
int n = Foo1(5);
int n2 = Foo1<int>(3);
double n3 = Foo1<double>(3.14);
int n4 = Foo1(3);
double n5 = Foo1(3.14);
}
}
① Generic Method를 사용하는 방법
이번엔 인자 2개를 받아보자.
using System;
class Program {
public static T Foo2<T>(T a, T b) {
Type t = a.GetType();
Console.WriteLine(t.FullName);
return a;
}
static void Main() {
Foo2(1, 2); // int
Foo2(1, 3.4); // double
Foo2(1, "AAA"); // error
Foo2<object>(1, "AAA"); // ok
}
}
인자 2개를 같은 타입으로 받는 메소드 Foo2이다.
11번째 라인의 Foo2(1, 2); 는 아무 문제없이 int타입으로 결정된다.
12번째 라인의 Foo2(1, 3.4); 는 C++에서는 에러가 나지만 C#에서는 컴파일러가 보고
double타입이면 양쪽 인자를 모두 담을 수 있는걸 확인 후 double로 결정된다. (더 큰 타입으로 결정)
13번째 라인의 Foo2(1, "AAA"); 는 int거나 string 둘 다 양쪽을 담지 못하기에 에러가 난다.
이 에러를 없앨 수는 있다. object로 받으면 된다.
728x90
반응형
'프로그래밍 > C#' 카테고리의 다른 글
[C#] Delegate (1) (0) | 2020.03.30 |
---|---|
[C#] 제너릭 제약 (Generic Constraint) (0) | 2020.03.27 |
[C#] 인덱서 (Indexer) (0) | 2020.03.19 |
[C#] 속성 (Property) (2) (0) | 2020.03.13 |
[C#] 속성 (property) (1) (0) | 2020.03.12 |