728x90
반응형
1. casting
using System;
class Program {
static void Main() {
int n = 3;
double d = 3.4;
d = n; // int => double - 데이터 손실 없음
n = d; // double => int - 데이터 손실 방생 error
n = (int)d;
}
}
① 캐스팅 규칙
=> 데이터 손실이 발생하지 않은 경우 암시적 형 변환 될 수 있다.
=> 데이터 손실이 발생하는 경우 명시적 캐스팅을 해야 한다.
2. is, as
using System;
class Animal { }
class Dog : Animal {
public void Cry() { Console.WriteLine("Dog Cry"); }
}
class Program {
public static void foo(Animal a) {
a.Cry();
}
static void Main() {
foo(new Dog());
}
}
함수 foo가 Animal을 인자로 받고 있으며, Animal의 모든 파생 클래스 또한 인자가 될 수 있다.
Main에서 Dog를 만들어서 보냈다.
분명 Dog안에는 Cry함수가 있지만, 하지만 Animal에는 Cry가 없으므로 호출할 수 없다. (에러)
이럴 경우 Aniaml 타입을 Dog 타입으로 다운캐스팅해서 사용할 수 있다.
using System;
class Animal { }
class Dog : Animal {
public void Cry() { Console.WriteLine("Dog Cry"); }
}
class Program {
public static void foo(Animal a) {
// a.Cry();
// Animal 참조 타입을 Dog 참조 타입으로 캐스팅
Dog d = (Dog)a;
d.Cry();
}
static void Main() {
// foo(new Dog());
foo(new Animal());
}
}
근데 문제는, foo는 사실 Dog를 받는게 아닌 Animal을 받고 있다.
그래서 foo(new Animal()); 을 Main에서 실행한다면 캐스팅이 잘 못되어 예외가 발생한다.
따라서 무조건 사용할 수 없고 타입을 조사한 후 사용해야 한다.
using System;
class Animal { }
class Dog : Animal {
public void Cry() { Console.WriteLine("Dog Cry"); }
}
class Program {
public static void foo(Animal a) {
// a.Cry();
// Animal 참조 타입을 Dog 참조 타입으로 캐스팅
// Dog d = (Dog)a;
// d.Cry();
if (a is Dog) {
Dog d = (Dog)a;
d.Cry();
}
}
static void Main() {
foo(new Dog());
foo(new Animal());
}
}
① is 연산자
=> 참조 변수가 가리키는 실제 타입을 조사 할 때 사용
using System;
class Animal { }
class Dog : Animal {
public void Cry() { Console.WriteLine("Dog Cry"); }
}
class Program {
public static void foo(Animal a) {
// a.Cry();
// Animal 참조 타입을 Dog 참조 타입으로 캐스팅
// Dog d = (Dog)a; // 실패시 예외
Dog d = a as Dog; // 실패시 null 반환
if(d!=null) {
d.Cry();
}
}
static void Main() {
foo(new Dog());
foo(new Animal());
}
}
② 2가지 캐스팅 방법
using System;
class Program {
static void Main() {
int n = 3;
object obj = n;
// int n1 = obj as int; // error (값 타입에 null을 넣을 수 없다.)
int? n1 = obj as int?; // ok
}
}
3. 변환 연산자
using System;
class Point {
private int x;
private int y;
public Point(int xPos, int yPos) {
x = xPos;
y = yPos;
}
public override string ToString() {
return string.Format($"{x}, {y}");
}
}
class Program {
static void Main() {
double d = 3.4;
// int n1 = d; // error
int n1 = (int)d; // ok
Point pt = new Point(1, 2);
int n2 = pt;
}
}
17~19라인의 코드는 위의 내용대로 명시적 캐스팅을 한 경우이다.
21~22라인의 코드는 pt 객체를 int에 넣어본 것이다.
하지만 컴파일러는 당연히 사용자 정의 타입을 int에 어떻게 넣는지 몰라 에러가 난다.
하지만 이걸 가능하게 할 수 있다.
① Point => int
=> public static explicit operator int(Point pt)
using System;
class Point {
private int x;
private int y;
public Point(int xPos, int yPos) {
x = xPos;
y = yPos;
}
public override string ToString() {
return string.Format($"{x}, {y}");
}
public static explicit operator int(Point pt) {
return pt.x;
}
}
class Program {
static void Main() {
double d = 3.4;
// int n1 = d; // error
int n1 = (int)d; // ok
Point pt = new Point(1, 2);
// int n2 = pt;
int n2 = (int)pt; // 명시적 형변환 필수
}
}
위의 내용은 명시적으로 꼭 타입을 적어주어야 한다.
using System;
class Point {
private int x;
private int y;
public Point(int xPos, int yPos) {
x = xPos;
y = yPos;
}
public override string ToString() {
return string.Format($"{x}, {y}");
}
public static explicit operator Point(int n) {
return new Point(n, n);
}
}
class Program {
static void Main() {
int n = 1;
Point pt = (Point)n;
Console.WriteLine(pt);
// Point pt2 = n2 as Point; // error
}
}
② int => Point
=> public static explicit operator Point(int pt)
③ as 연산자 사용시 변환연산자가 호출되지 않는다.
728x90
반응형
'프로그래밍 > C#' 카테고리의 다른 글
[C#] Boxing / Unboxing (2) (1) | 2020.02.11 |
---|---|
[C#] Boxing / Unboxing (1) (1) | 2020.02.10 |
[C#] Elvis Operator (?, ??) 연산자 (0) | 2020.02.06 |
[C#] Nullable<T> (0) | 2020.02.04 |
[C#] 동등성 (Equality) (0) | 2020.02.04 |