본문 바로가기

.NET/C#

[C#] as, is 키워드 사용법

형식을 변환하기 위해 캐스트 연산자를 사용한다.

double pi = 3.14;
int p = (int)pi;	// double 타입 값 3.14를 int 타입으로 캐스팅

이런 식으로 값을 다른 형식으로 변환하거나,

 

enum FruitType
{
	Apple,
    Banana,
    Grape,
    Orange,
    Pineapple,
    Mango
}

static void Main(string[] args)
{
	int i = (int)FruitType.Apple;
    FruitType f = (FruitType)2;
}

이런 식으로 열거형에도 사용할 수 있고,

 

private void button_Click(object sender, EventArgs e)
{
	MessageBox.Show(((Button)sender).Text + " Clicked.");
}

이렇게 참조 형식 형변환에도 물론 사용 가능하다.

 

그러나 위 방법은 참조 형식에 대해서는 썩 좋은 방법은 아니다.

가령 어떤 클래스의 인스턴스를 전혀 다른 클래스의 참조 변수로 참조하기 위해 아래와 같이 캐스팅을 수행하면 예외가 발생할 것이다.

class ClassA {}

class ClassB {}

static void Main(string[] args)
{
	object a = new ClassA();
    ClassB b = (ClassB)a;	// InvalidCastException : ClassA 형식 개체를 ClassB 형식으로 캐스팅할 수 없습니다.
}

 

참조 형식에 대해서는 as 키워드를 사용해 캐스팅할 수 있다.

캐스트 연산자와 as의 다른 점은 캐스트 연산자는 위와 같이 형변환에 실패할 경우 예외를 던지지만, as 키워드는 형변환에 실패한 경우 예외를 던지지 않고 null을 대입해준다.

class ClassA {}

class ClassB {}

static void Main(string[] args)
{
	object a = new ClassA();
    ClassB b = a as ClassB;	// 캐스팅 불가하므로 b에는 null이 대입
}

 

is 키워드는 캐스팅이 가능한지의 여부를 bool 값으로 돌려준다.

class ClassA {}

class ClassB {}

static void Main(string[] args)
{
	object a = new ClassA();
    ClassB b;
    
    if(a is ClassB) b = a as ClassB;
    else b = new ClassB();
}

 

주의할 점은 as 키워드는 null을 허용할 수 있는 참조 형식에 대해서만 사용이 가능하다는 점이다. 아래와 같이 값 혹은 값 형식 변수에 대해서는 사용할 수 없다. 값 형식 변수에는 혹시 캐스팅이 실패하더라도 null을 대입하는 것이 불가능하기 때문이다.

void func(object a)
{
	if (a is double) var b = a as double;	// 컴파일 에러.
}

위와 같이 is를 사용해 형변환이 가능한지의 여부는 확인이 가능하나, as를 사용해서 형변환 시도를 하는 것은 불가능하다.

 


is 키워드는 조건식 등에서 아주 강력한 성능을 낼 수 있다.

void func (object obj)
{
	if (obj is TextBox box) MessageBox.Show($"TextBox:{box.Name} ({box.Text})");
    else if (obj is NumericUpDown num) MessageBox.Show($"NumericUpDown:{num.Name} ({num.Value})");
}

obj is TextBox box 이 문장은 obj가 TextBox로 변환 가능한 경우 변환하여 변수 box에 대입해주며, 식의 결과값은 true가 된다. 이후 box 변수는 해당 문장이 포함된 블록 혹은 메서드가 종료될 때까지 유효하다.