[Effective C#] 형변환시 캐스트보다는 is, as

WH_NAM·2024년 2월 6일

Effective C#

목록 보기
3/23
post-thumbnail

Effective C# Itme3

C#에서의 형변환
컴파일러의 캐스트 연산자 구문 사용

object o = Factory.GetObject();

try
{
	MyType t;
    t = (MyType)o;	// 형 변환
}
catch (InvalidCastException)
{
	// 오류 보고
}

as 연산자를 사용

object o = Factory.GetObject();

MyType t = o as MyType;

if (t != null)
{
	// MyType 타입의 t 객체 사용
}
else
{
	// 오류 보고
}

is 연산자를 사용

object o = Factory.GetObject();

MyType t;

if (o is MyType)
{
	t = o;
	// MyType 타입의 t 객체 사용
}
else
{
	// 오류 보고
}

as를 사용할 경우 작성하기 더 쉽고 읽기도 편하다. try/catch 문이 없기 때문에 성능도 좋다.

as 연산자와 캐스팅의 차이점
as, is : 런타임에 객체 타입을 확인하고 필요에 따라 박싱을 수행. 객체를 다른 타입으로 형변환하려면 이 객체는 지정한 타입이거나 혹은 지정한 타입을 상속한 타입이어야 한다. 그 외의 경우는 모두 실패

캐스트 : 타입 변환시 형변환 연산자가 개입될 수 있다. 대표적인 형변환 연산자는 숫자 타입에 대한 형변환 연산자(long->short로 변환시 일부 정보를 잃는다.)

사용자가 정의한 타입에서의 문제

public class SecondType
{
	private MyType _value;

    // 중략

    // 사용자 정의 형변환 연산자
    // SecondType을 MyType 타입으로 변환한다.
    public static implicit operator MyType(SecondType t)
    {
    	return t._value;
    }
}

다음 코드에서 Factory.GetObject() 메서드가 앞의 코드에서 정의한 SecondType의 객체를 반환한다고 가정하자

object o = Factory.GetObject(); // o는 SecondType

// ver 1 - as 사용
MyType t1 = o as MyType;

if (t1 != null)
{
	// MyType 타입의 t1 객체 사용
}
else
{
	// 오류 보고
}

// ver 2 - 캐스트 사용
try
{
	MyType t2;
    t2 = (MyType)o;
    // MyType 타입의 t2 객체 사용
}
catch (InvalidCastException)
{
	// 형변환 오류 보고
}

두 버전 모두 형변환에 실패한다.
사용자 정의 형변환 연산자에 의해 버전2는 성공했어야 한다.

  • 컴파일러는 객체 o가 런타임에 어떤 타입인지를 알 방법이 없다.
  • 따라서 컴파일러는 객체 o가 object 타입이라고 생각한다.
  • object 타입을 MyType으로 형변환할 수 있는 연산자가 정의됐는지만 확인한다.
  • 컴파일러는 객체 o가 MyType 형식인지를 확인하는 코드만 생성한다.
  • 런타임에 객체 o는 SecondType 형식의 객체이므로 형변환에 실패한다.

사용자 정의 형변환 연산자는 객체의 런타임 타입이 아닌 컴파일타임 타임에 맞춰 수행된다.

value type/사용자 정의 형변환을 제외한 경우에는 is/as연산자를 사용하는 것이 좋다.

profile
안녕하세요

0개의 댓글