이 연습 문제는 여러 숫자형이 오버플로할 때, 즉 산술 연산이나 캐스트 같은 계산으로 나온 값을 담기에 용량이 부족할 때 어떤 동작을 보이는지 보여줘요.
byte, ushort, uint, ulong)는 0으로 되돌아가요(그 타입의 최댓값 + 1이 나머지 연산의 기준이 돼요). 다만 대체로 checked 블록 안에 있는 경우에는 OverflowException이 발생해요. int와 long도 비슷하게 동작하지만, 각각 int.MinValue와 long.minValue로 되돌아간다는 점이 달라요.int one = 1;
checked
{
int expr = int.MaxValue + one; // overflow exception is thrown
}
// or
int expr2 = checked(int.MaxValue + one); // overflow exception is thrown
checked 상태는 블록 안에 직접 있는 식에만 적용돼요. 호출된 함수에서 발생하는 오버플로는 잡지 못해요.float과 double 타입은 무한대 상태가 되고, float.IsInfinity() 등으로 검사할 수 있어요.double d = double.MaxValue;
d *= 2d;
Double.IsFinite(d)
// => false
decimal 타입의 숫자는 OverflowException을 발생시켜요.checked 블록 안에서 unchecked의 효과를 되돌리고 싶을 때, 또는 컴파일러 설정을 사용했을 때를 위한 unchecked 키워드도 있어요.예외가 발생하지 않는 오버플로는 문제가 될 수 있어요. 오류 상황은 가능한 한 빨리 알려 주는 편이 좋으니까요.
int와 float의 오버플로 문제는 결과를 long, decimal, double 타입의 변수에 대입하면 어느 정도 완화할 수 있어요.
코드에 큰 정수가 꼭 필요하다면 BigInteger 타입을 사용하는 방법도 있어요.
물론 정수가 되돌아가도록 놔두는 것이 정당한 경우도 있어요. 특히 부호 없는 값에서 그렇죠. 대표적인 예가 정수의 폭을 일종의 나머지 연산 기준으로 사용하는 해시 코드예요.
코드베이스에서는 uint나 ulong을 식별자로 쓸 때 검사를 하지 않는 경우가 흔해요. 이득보다 번거로움이 크다고 여기기 때문이죠. 도메인상 아주 큰 값이 나오지 않는다는 게 분명할 때도 마찬가지고요. 하지만 교훈 삼을 만한 사례가 궁금하다면 이 영상을 봐요.