[C#] 상속 관계에 있는 클래스의 형변환

is 연산자와 as 연산자




C++의 다운 캐스팅과 연관된 연산자인 듯 하다.

예전 dynamic_cast<>를 공부할 때 비슷한 내용을

다뤘던 것 같다. C#에서는 좀 더 세련된(?) 형변환을

위해 멋진 연산자 두 개를 제공한다. 바로 is와 as




class Mammal{

public void Nurse() { ... }

}


class Dog : Mammal {

public void Bark() { ... }

}


class Cat : Mammal {

public void Meow() { ... }

}


익히 알고 있듯이 포유류는 포유류 이고

개도 고양이도 모두 포유류이다.


Mamal m = new Mammla();

m.Nurse();


m = new Dog();

m.Nurse();


Dog dog = (Dog)m;     // 다운 캐스팅이다.

dog.Nurse();                // 하지만 m이 가리키고 있는 것이

dog.Bark();                  // Dog이기 때문에 가능하다.


m = new Cat();

m.Nurse();


Cat cat = (Cat)m;        // 역시 다운 캐스팅.

cat.Nurse();                // 하지만 m이 가리키고 있는 것이

cat.Meow();                // Cat이기 때문에 가능하다.




위의 코드를 is 와 as 연산자를 사용해서 바꾸어보자.

먼저 is와 as를 간단하게 설명하자면


is

객체가 해당 형식에 해당하는지 검사하여

그 결과를 bool 값으로 반환한다.


as

형식 변환 연산자와 같은 역할을 한다.

다만 형변환 연산자가 변환에 실패하는 경우에

예외를 던지는 반면, as 연산자는 객체 참조를

null로 만들어 버린다. (dynamic_cast와 같은 성질)




Mammal m = new Dog();

Dog dog;


if( m is Dog ){                    // 말그대로  m 이 Dog를 가리키고 있니?

dog = (Dog)m;

dog.Bark();

}


Mammal m2 = new Cat();

Cat cat = m2 as Cat;         // m2를 Cat으로 형변환하라.

if( cat != null ){                 // 다운 캐스팅을 하라는 말인데

cat.Meow();             // 이 경우 m2는 Cat를 가리키고 있기 때문에 가능하다.

}                                      // 만약 m2 = new Mammal() 이었다면 불가능.

 // 파생 클래스는 기본 클래스보다 더 많은 정보를 담고 있는데

 // 기본 클래스에 없는 부분을 호출하려 한다면 문제가 발생.

// 때문에 이 경우 cat는 null이 된다.




C++의 시점에서 설명이 된 듯한데

확실히 C++의 dynamic_cast<> 보다는

훨씬 사용법이 간편한 것 같다.




일반적으로 형식 변환 연산자 대신 as 연산자를

사용하는 쪽이 더 권장 되는데, 형식 변환에 실패하더라도

예외가 일어나 갑자기 코드의 실행이 갑자기 점프하는 일이

없으므로 코드 관리가 더 수월해지기 때문이란다.


주의해야할 점은 as 연산자는 참조 형식에 대해서만

사용이 가능하므로 값 형식의 객체는 기존의 형식

변환 연산자를 사용해야 한다.





+ Recent posts