C++ 쟁이가 C#을 배워보자 - 타입 변환

오늘은 foreach에 이어 C#의 타입변환에 대해 포스팅 해본다. 이전과 마찬가지로 C++과 다른 부분에 집중한 포스팅이다.

1. 숫자 타입 변환

C++에서는 크기가 큰 타입에서 작은 타입으로 묵시적인 형변환을 하는 경우 컴파일시 값이 잘릴 수 있다는 경고를 보내준다. 그러나 C#에서는 작은 타입으로의 묵시적 형변환은 컴파일 시 에러를 발생시킨다.(참고 : VS2015 이후 부터는 포인터 타입 형변환 시 포인터 변수의 크기보다 작은 타입으로 변환하는 경우 컴파일 에러가 발생한다. 이는 reinterpret_cast를 하더라도 발생한다.)
//아래 코드는 C++에서는 Warning을 발생시키지만 C#에서는 에러로 처리한다.
//8바이트 double형 데이터를 4바이트 int으로 변환 시도

double d = 1.0;
int i = d; //값이 유실될 수 있음!!

위와 같은 경우에는 명시적으로 형변환을 하겠다고만 하면 컴파일 에러는 해결이 된다.
double d = 1.0;
int i = (int)d; //(int)를 넣으므로 명시적으로 변환하겠다고 선언
그러나 명시적으로 변환한다고 모든것이 해결이 되는 것은 아니다.int형을 short형으로 명시적 형변환을 한다고 생각하면, int형 변수의 값이 short로 표현할 수 있는 범위를 넘는 경우 overflow가 발생하여 의도하지 않은 값이 들어가게 된다.
int val = 70000;
short sh = (short)val;
System.Console.WriteLine($"{sh}");
위 코드를 빌드 후 실행해보면 4464가 출력됨을 알 수 있다. 이는 short가 표현할 수 있는 범위인 -32768 ~ 32767을 벗어난 값이기 때문이다.

System.Convert 클래스를 이용한 형변환 및 반올림

형변환 연산자 외에도 System.Convert 클래스를 이용하여 변환이 가능하다. 그러나 연산자에 의한 형변환과 다른점을 보면 다음과 같다.
double d = 1.6;
int val = System.Convert.ToInt32(d);
WriteLine($"{val}"); //무엇이 출력될까?
위 코드를 실행해 보면 (int) d로 변환한 것과는 달리 "2"가 출력이 된다. 형변환 연산자에 의한 실수 -> 정수 변환은 소수점 이하를 버리는 반면에 System.Convert를 이용한 형변환은 소수점을 반올림하게 된다.그러나 C#은 일반적인 수학에서 사용하는 .5 이상인 경우 올림, 미만인 경우 버림을 하는 반올림이 아닌 은행원의 반올림(Banker's rounding) 이라는 방식으로 반올림 처리를 한다.
은행원의 반올림이란 간단하게 말하면 가장 가까운 짝수로 반올림을 하는 방식이다.
일반 반올림과 은행원의 반올림으로 반올림을 비교하면 아래 표와 같다.
원본값일반 반올림은행원의 반올림
1.4911
1.522
2.4922
2.532

2. string 변환

모든 타입은 System.Object로부터 파생된 ToString이라는 메서드를 가지고 있다. 이는 현재 값을 문자열로 변환하여 반환한다. 문자열 형태로 표현할 수 없는 일부 타입은 ToString 메서드가 네임스페이스와 타입 이름을 반환한다.
int val = 1224;
System.Console.WriteLine(number.ToString());
bool boolean = true;
System.Console.WriteLine(boolean.ToString());
DateTime now = DateTime.Now;
System.Console.WriteLine(now.ToString());
object me = new object();
System.Console.WriteLine(me.ToString());

3. string ↔ 다른 타입 변환

보통 문자열 ↔ 숫자 혹은 날짜를 변경하는 상황이 자주 발생하게 된다. 이를 위해 몇몇 객체는 Parse 메서드로 문자열을 해당 타입으로 바꿀 수 있도록 지원하고 있다.
int val = int.Parse("1224");
DateTime today = DateTime.Parse("2018-05-28 00:00:00 +09:00");
위 코드에서 날짜의 경우 포맷이 매우 다양하므로 아래 링크를 참조하면 된다.
표준 날짜 및 시간 형식 문자열
사용자 지정 날짜 및 시간 형식 문자열
그러나 아래와 같이 변환할 수 없는 경우에는 예외를 반환하게 되므로 TryParse 메서드를 이용하여 런타임에서 예외가 발생하지 않도록 처리가 필요하다.
int val = int.Parse("aaa"); // 런타임 에러 발생!!

//TryParse로 안전하게 변환한 경우
int val1;
string str = "aaa";

if (int.TryParse(str, out val1))
{
    //변환 성공!!
}
else
{
    //변환 실패!!
}

댓글

가장 많이 본 글