강제 형 변환보다는 as, is가 좋다!
C#에서도 C, C++, Java등에서 사용하던 강제 형 변환을 할 수 있다.
형 변환 예) |
void EventHandler(object obj, EventArgs e) { MyClass myClassByCast = (MyClass)obj; // cast사용 MyClass myClassByAs = obj as MyClass; // as 사용 } |
C#에서는 위처럼 object형을 형 변환해야 할 때가 종종 있다.
중요한 점은 위처럼 강제 cast를 하나 as키워드를 사용하나 그 결과는 같다는 것이다.
그렇다면 왜 as키워드를 사용해야 하는 걸까?
1. as나 is 연산자는 런타임에 객체의 형 변환이 가능한지를 확인하기 위해서 사용자가 정의한 형 변환 연산자를 고려하지 않는다. è 애초에 형 변환이 불가능 한 경우(객체가 변환 요청된 타입이거나 변환 요청타입으로부터 상속된 타입이 아닌 경우)에는 컴파일 때 에러를 발생한다.
반면 cast 연산의 경우 컴파일러는 객체를 변환 요청된 타입으로 변경할 수 있는 다양한 형 변환 연산자를 고려하여 형 변환을 수행하는 코드를 만들어낸다.
이러한 점을 고려하여 예외를 코려한 코드로 바꾼다면 이러한 식이 될 것이다.
예외상황을 고려한 형 변환 예) |
try { MyClass myClassByCast = (MyClass)obj; // cast사용 if (myClassByCast != null) { // 객체 사용 } else { // null일 경우 오류 보고 } } catch { // 형 변환 오류 보고 } MyClass myClassByAs = obj as MyClass; // as 사용 if (myClassByAs != null) { // 객체 사용 } else { // null일 경우 오류 보고 } |
눈에 띄는 점 두 가지는
1. 강제 형 변환의 경우 try catch를 사용하여 형 변환에 대한 예외를 따로 잡아야 한다는 점,
2. 어떠한 경우를 사용해도 null은 변환될 수 있기 때문에 if/else를 사용하여 잡아줘야 한다는 점
이 될 것이다.
위의 말을 종합하여 보았을 때 한마디로 요약하자면
‘강제 형 변환의 경우 형 변환이 수행될 수도 있고 그렇지 않을 수도 있지만, as 키워드를 사용하면 형 변환이 100% 수행될 것이라 판단할 수 있다.’
그렇다면 is키워드는 언제 사용하는 것 인가?
그것은 어쩔 수 없이 강제 형 변환을 사용할 경우가 생길 때 이다.
as키워드는 변환할 타입이 Reference형일 때만 사용할 수 있다. 즉 value타입은 as키워드를 사용하여 형 변환할 수 없으며, 이럴 때 강제 형 변환을 사용하게 된다. 하지만 위 내용과 같이 강제 형 변환은 형 변환 수행에 대한 보장을 하지 않기 때문에, 형 변환 가능 여부를 미리 살피기 위해 is키워드를 사용한다.
예를 들어 object형을 int로 변환하려 한다면 as키워드는 동작하지 않는다.(컴파일 에러)
value타입으로의 형 변환 |
object o = MyClass.GetValue(); int i = (int)o; // 동작 int j = o as int; // 에러 |
에러 메시지는 다음과 같다 :
오류 : as 연산자는 참조 형식 또는 nullable 형식과 함께 사용해야 합니다. 'int'은(는) null을 허용하지 않는 값 형식입니다.
이런 경우에 is연산자를 사용할 수 있다.
is 연산자를 사용함으로써 얻을 수 있는 이점은 위에서 말한 것과 같이 형 변환 수행동작을 보장할 수 있기 때문에 굳이 try / catch를 사용하지 않아도 된다는 점이다.
위의 예제를 is키워드를 사용하여 예외를 고려한 코드로 바꾼다면 다음과 같다.
value타입으로의 형 변환 |
object o = MyClass.GetValue(); int i; if(o is int) i = (int)o; // 동작 |
요약 :
1. Reference 타입의 형 변환을 할 경우 as연산자를 사용하여 형 변환을 보장하자!
2. 강제 형 변환을 사용할 경우 is키워드를 사용하여 형 변환을 보장하자!
WebClient Download Sample (0) | 2011.11.17 |
---|---|
c# 시간 측정 방법 (0) | 2011.11.04 |
SqlBulkCopy (0) | 2011.10.22 |
enum 의 flags 연산 (0) | 2011.06.14 |
TreeView 검색(재귀호출) (0) | 2011.05.16 |