프로그래밍 언어 공부 중 형변환을 사용한다면 보편적으로 일반적인 Cast 방식을 사용합니다.
private static void Main(string[] args)
{
int intValue = 0;
long longValue = 2147483647; // = int.MaxValue
intValue = (int)longValue;
Console.WriteLine(intValue);
// Result
// 2147483647
}
위와 같은 방식으로 long형에서 int형으로 데이터형이 작은쪽으로도 변환이 가능합니다. (8byte to 4byte)
그렇다면 아래와 같은 방식은 어떨까요?
private static void Main(string[] args)
{
int intValue = 0;
long longValue = 9223372036854775807; // = long.MaxValue
intValue = (int)longValue;
Console.WriteLine(intValue);
// Result
// -1
longValue = intValue;
Console.WriteLine(longValue);
// Result
// -1
}
int형의 최대범위를 초과하여 문제가 생기며, 데이터 손실이 되어버립니다. (일명 쓰레기값이 되어렸습니다.)
추가된 코드로 다시 되돌려보아도 이미 손실이 생겨 원래의 값을 잃어버렸습니다. 일반적으로 사용되었던 Cast방식을 사용한다면 이러한 문제가 생길 수 있습니다. 우리는 이러한 사실을 간과하고 놓칠 수 있겠죠.
그러면 애당초 형변환을 실패했다면 강제로 형변환 시키지 않도록 하는 방법은 없을까요?
이러한 문제점을 해결해주는 것으로 닷넷에서는 as와 is 사용을 권장하고 있습니다. 하지만 위와 같이 struct(구조체) 형식에서는 사용을 할 수 없습니다.
대신 class에서는 사용이 가능하며, 이는 반대로 클래스와 구조체에게 있어서 케스팅 방식을 따로 권장하고 있습니다.
private class Animal
{
int age = 0;
}
private class Human : Animal
{
// Human Values..
}
private class Dog : Animal
{
// Dog Values..
}
private class Cat : Animal
{
// Cat Values..
}
private static void Main(string[] args)
{
Animal animal = new Animal();
Human human = new Human();
Dog dog = new Dog();
Cat cat = new Cat();
human = dog as human; // error
dog = dog as cat; // error
animal = human as animal; // error
animal = (Animal)human; // Loss Human Values Data
}
작성간 에러를 바로 확인 할 수 있는 방법이기도 하며, 아래와 같이 장점이 있습니다.
1. 방어적인 형변환 기법이다.
2. 강제형 변환이 옳은지 try/catch를 사용할 필요가 없으며, 한 줄 코드로 간결해진다. (안정적이다. 런타임에 효율적이다.)
3. 형변환이 정상적으로 되었는지 확인이 가능하다. (데이터 손실이 일어나지 않게 할 수 있다.)
4. 성능적인 면에서 좋다.
아래는 닷넷에서 제공하는 예제입니다.
IEnumerable<int> numbers = new[] { 10, 20, 30 };
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); // output: 40
}
해당 데이터형이 먼저 List형식인지 확인이 가능하며 이상 없이 스크립트가 실행되었습니다. 이는 try/catch를 사용하지 않고 얻을 수 있는 최적화적인 방법 중에 하나입니다.
추가로 요약을 하자면, 강제형변환보다는 is 나 as를 먼저 사용하고, 해당되지 않는다면 일반적인 강제형변환을 사용하는 것이 좋다고 할 수 있습니다.
성능적인 면에서도 강제형변환보다는 좋습니다. 아래의 예제를 통해 알아봅시다.
if (myobject is Student)
{
Student objStudent = (Student)myobject;
}
해당 오브젝트가 먼저 학생인지 확인하고, 학생이 맞다면 형변환을 시도합니다. 코드 작성간 이상은 없지만, 우리가 원하는 사용 이유는 아닙니다.
조금 더 간결하게 수정하자면, 아래와 같은 코드가 됩니다.
Student objStudent = (Student) myobject;
간결하지만, 이는 해당 오브젝트가 학생이 맞는지도 정확하지 않은 상황에서 예외상황을 초래할 수 있습니다.
다시 아래와 같이 수정합니다.
Student objStudent = myobject as Student;
if (objStudent != null)
{
//use the object
}
as 키워드는 변환 중 이상이 있다면 null을 반환합니다. 이상이 없다면 바로 코드를 사용할 수 있는 상태가 됩니다. 처음에는 형변환을 위해 두 번의 과정이 있었지만, 지금은 형변환을 한 번에 수행하였습니다.
이와 같이 C# 스크립트 작성 중에는 강제형변환 보다는 as, is를 먼저 고려하는 쪽이 좋다고 할 수 있겠습니다.
참고: https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/operators/type-testing-and-cast
참고: https://codewala.net/2011/03/11/is-vs-as-operators-performance-implications/
'Study' 카테고리의 다른 글
디자인 패턴, Singleton Pattern (단일 인스턴스 패턴) (0) | 2022.01.31 |
---|---|
디자인 패턴, Flyweight Pattern (경량 패턴) (0) | 2022.01.30 |
디자인 패턴, Observer Pattern (관찰자 패턴) (0) | 2022.01.29 |
디자인 패턴, Build Pattern (생성 패턴) (2) | 2022.01.22 |
A* 알고리즘 구현 (Unity, C# 환경) (0) | 2021.12.26 |
댓글