형식 테스트 연산자 및 캐스트 식 - is, as, typeof 및 캐스트

이러한 연산자와 식은 형식 검사 또는 형식 변환을 수행합니다. is연산자는 식의 런타임 형식이 지정된 형식과 호환되는지 확인합니다. as연산자는 런타임 형식이 지정된 형식과 호환되는 경우 식을 해당 형식으로 명시적으로 변환합니다. 캐스트 식은 대상 형식으로의 명시적 변환을 수행합니다. typeof연산자는 형식의 System.Type 인스턴스를 가져옵니다.

is 연산자

is 연산자는 식 결과의 런타임 형식이 지정된 형식과 호환되는지 확인합니다. is 연산자는 식 결과에 패턴이 있는지도 테스트합니다.

형식 테스트 is 연산자가 포함된 식의 양식은 다음과 같습니다.

E is T

여기서 E는 값을 반환하는 식이고, T는 형식 또는 형식 매개 변수의 이름입니다. E는 무명 메서드 또는 람다 식일 수 없습니다.

is 연산자는 식 결과가 null이 아니고 다음 조건 중 하나라도 충족되면 true를 반환합니다.

  • 식 결과의 런타임 형식은 T입니다.

  • 식 결과의 런타임 형식은 T 형식에서 파생되거나 인터페이스 T를 구현합니다. 또는 여기에서 T로 또 다른 암시적 참조 변환이 존재합니다.

  • 식 결과의 런타임 형식은 기본 형식 T를 사용하는 nullable 값 형식이고, Nullable<T>.HasValuetrue입니다.

  • 식 결과의 런타임 형식에서 T 형식으로 boxing 또는 unboxing 변환이 존재합니다.

is 연산자는 사용자 정의 변환을 고려하지 않습니다.

다음 예제에서는 식 결과의 런타임 형식이 지정된 형식에서 파생되는 경우, 즉 형식 간에 참조 변환이 있는 경우 is 연산자가 true를 반환하는 것을 보여 줍니다.

public class Base { }

public class Derived : Base { }

public static class IsOperatorExample
{
    public static void Main()
    {
        object b = new Base();
        Console.WriteLine(b is Base);  // output: True
        Console.WriteLine(b is Derived);  // output: False

        object d = new Derived();
        Console.WriteLine(d is Base);  // output: True
        Console.WriteLine(d is Derived); // output: True
    }
}

다음 예제에서는 is 연산자가 boxing 및 unboxing 변환은 고려하지만 숫자 변환을 고려하지 않는 것을 보여 줍니다.

int i = 27;
Console.WriteLine(i is System.IFormattable);  // output: True

object iBoxed = i;
Console.WriteLine(iBoxed is int);  // output: True
Console.WriteLine(iBoxed is long);  // output: False

C# 변환에 대한 자세한 내용은 C# 언어 사양변환 장을 참조하세요.

패턴 일치를 사용한 형식 테스트

is 연산자는 식 결과에 패턴이 있는지도 테스트합니다. 다음 예제에서는 선언 패턴을 사용하여 식의 런타임 형식을 확인하는 방법을 보여 줍니다.

int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
    Console.WriteLine(a + b);  // output 30
}

지원되는 패턴에 대한 자세한 내용은 패턴을 참조하세요.

as 연산자

as 연산자는 식의 결과를 지정된 참조 또는 nullable 값 형식으로 명시적으로 변환합니다. 변환할 수 없는 경우 as 연산자가 null을 반환합니다. 캐스트 식과 달리 as 연산자는 예외를 throw하지 않습니다.

다음 형태의 식이 있다고 가정합니다.

E as T

여기서 E는 값을 반환하는 식이고, T는 형식 또는 형식 매개 변수의 이름입니다. 이 식은 다음과 동일한 결과를 생성합니다.

E is T ? (T)(E) : (T)null

단, E가 한 번만 계산됩니다.

as 연산자는 참조, nullable, boxing 및 unboxing 변환만 고려합니다. as 연산자를 사용하여 사용자 정의 변환을 수행할 수는 없습니다. 이렇게 하려면 캐스트 식을 사용합니다.

다음 예제에서는 as 연산자의 사용법을 보여 줍니다.

IEnumerable<int> numbers = new List<int>(){10, 20, 30};
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
    Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]);  // output: 40
}

참고

앞의 예제와 같이, as 식의 결과를 null과 비교하여 변환에 성공했는지 확인해야 합니다. is 연산자를 사용하여 변환에 성공하는지 테스트하고, 성공한 경우 해당 결과를 새 변수에 할당할 수 있습니다.

캐스트 식

(T)E 형태의 캐스트 식은 E 식의 결과를 T 형식으로 명시적으로 변환합니다. E 형식에서 T 형식으로의 명시적 변환이 없는 경우 컴파일 시간 오류가 발생합니다. 런타임에 명시적 변환이 실패하고 캐스트 식이 예외를 throw할 수도 있습니다.

다음 예제에서는 명시적 숫자 및 참조 변환을 보여 줍니다.

double x = 1234.7;
int a = (int)x;
Console.WriteLine(a);   // output: 1234

int[] ints = [10, 20, 30];
IEnumerable<int> numbers = ints;
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count);  // output: 3
Console.WriteLine(list[1]);  // output: 20

지원되는 명시적 변환에 대한 자세한 내용은 C# 언어 사양명시적 변환 섹션을 참조하세요. 사용자 지정 명시적 또는 암시적 형식 변환을 정의하는 방법에 대한 자세한 내용은 사용자 정의 변환 연산자를 참조하세요.

다른 () 용도

메서드 또는 대리자를 호출하는 경우에도 괄호를 사용합니다.

괄호를 사용하여 식에서 연산을 계산하는 순서를 조정하기도 합니다. 자세한 내용은 C# 연산자를 참조하세요.

typeof 연산자

typeof 연산자는 형식의 System.Type 인스턴스를 가져옵니다. typeof 연산자의 인수는 다음 예제와 같이 형식 또는 형식 매개 변수의 이름이어야 합니다.

void PrintType<T>() => Console.WriteLine(typeof(T));

Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]

인수는 메타데이터 주석이 필요한 형식이 아니어야 합니다. 예제에는 다음 유형이 포함됩니다.

  • dynamic
  • string?(또는 nullable 참조 형식)

이러한 형식은 메타데이터에서 직접 표시되지 않습니다. 형식에는 기본 형식을 설명하는 특성이 포함됩니다. 두 경우 모든 기본 형식을 사용할 수 있습니다. dynamic 대신 object를 사용할 수 있습니다. string? 대신 string을 사용할 수 있습니다.

바인딩되지 않은 제네릭 형식과 typeof 연산자를 사용할 수도 있습니다. 바인딩되지 않은 제네릭 형식의 이름에는 형식 매개 변수 개수보다 하나 더 적은 적절한 개수의 쉼표가 포함되어야 합니다. 다음 예제에서는 바인딩되지 않은 제네릭 형식과 typeof 연산자를 사용하는 방법을 보여 줍니다.

Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]

식은 typeof 연산자의 인수가 될 수 없습니다. 식 결과의 런타임 형식에 대한 System.Type 인스턴스를 가져오려면 Object.GetType 메서드를 사용합니다.

typeof 연산자를 사용한 형식 테스트

typeof 연산자를 사용하여 식 결과의 런타임 형식이 지정된 형식과 정확히 일치하는지 확인합니다. 다음 예제에서는 typeof 연산자와 is 연산자로 수행되는 형식 검사의 차이점을 보여 줍니다.

public class Animal { }

public class Giraffe : Animal { }

public static class TypeOfExample
{
    public static void Main()
    {
        object b = new Giraffe();
        Console.WriteLine(b is Animal);  // output: True
        Console.WriteLine(b.GetType() == typeof(Animal));  // output: False

        Console.WriteLine(b is Giraffe);  // output: True
        Console.WriteLine(b.GetType() == typeof(Giraffe));  // output: True
    }
}

연산자 오버로드 가능성

is, astypeof 연산자는 오버로드할 수 없습니다.

사용자 정의 형식은 () 연산자를 오버로드할 수 없지만, 캐스트 식에서 수행할 수 있는 사용자 지정 형식 변환을 정의할 수 있습니다. 자세한 내용은 사용자 정의 변환 연산자를 참조하세요.

C# 언어 사양

자세한 내용은 C# 언어 사양의 다음 섹션을 참조하세요.

참고 항목