다음을 통해 공유


System.InvalidCastException 클래스

이 문서는 이 API에 대한 참조 설명서를 보충하는 추가 설명을 제공합니다.

.NET은 파생 형식에서 기본 형식으로의 자동 변환과, 그리고 원래의 파생 형식으로 다시 변환을 지원합니다. 또한, 인터페이스를 제공하는 형식에서 인터페이스 개체로의 변환 및 그 반대 방향으로의 자동 변환도 지원합니다. 또한 사용자 지정 변환을 지원하는 다양한 메커니즘을 포함합니다. 자세한 내용은 .NET의 형식 변환을 참조하세요.

InvalidCastException 한 형식의 인스턴스를 다른 형식으로 변환할 수 없는 경우 예외가 throw됩니다. 예를 들어 Char 값을 DateTime 값으로 변환하려고 시도하면 InvalidCastException 예외가 발생합니다. 한 형식을 다른 형식으로 변환할 수 있는 경우에도, 원본 형식의 값이 대상 형식의 범위를 초과할 때 발생하는 예외와는 다릅니다 OverflowException. InvalidCastException 예외는 개발자 오류로 인해 발생하며 블록에서 try/catch 처리해서는 안 됩니다. 대신 예외의 원인을 제거해야 합니다.

시스템에서 지원하는 변환에 대한 자세한 내용은 클래스를 Convert 참조하세요. 대상 형식이 원본 형식 값을 저장할 수 있지만 특정 원본 값을 저장할 만큼 크지 않을 때 발생하는 오류는 예외를 OverflowException 참조하세요.

비고

대부분의 경우 언어 컴파일러는 원본 형식과 대상 형식 간에 변환이 없음을 감지하고 컴파일러 오류를 발생합니다.

변환 시도가 예외 InvalidCastException를 발생시키는 조건 중 일부는 다음 섹션에서 설명합니다.

명시적 참조 변환에 성공하려면 원본 값이어야 null합니다. 또는 소스 인수에서 참조하는 개체 형식을 암시적 참조 변환을 통해 대상 형식으로 변환할 수 있어야 합니다.

다음 중간 언어(IL) 명령은 InvalidCastException 예외를 throw합니다.

  • castclass
  • refanyval
  • unbox

InvalidCastException 는 값이 0x80004002 HRESULT COR_E_INVALIDCAST를 사용합니다.

InvalidCastException인스턴스의 초기 속성 값 목록은 InvalidCastException 생성자를 참조하세요.

기본 형식 및 IConvertible

특정 변환을 지원하지 않는 기본 형식의 IConvertible 구현을 직접 또는 간접적으로 호출합니다. 예를 들어, Boolean 값을 Char로 변환하거나, DateTime 값을 Int32로 변환하려고 하면 InvalidCastException 예외가 발생합니다. 다음 예제에서는 Boolean.IConvertible.ToChar 값을 Convert.ToChar(Boolean)로 변환하기 위해 Boolean 메서드와 Char 메서드를 모두 호출합니다. 두 경우 모두 메서드 호출이 InvalidCastException 예외를 발생시킵니다.

using System;

public class IConvertibleEx
{
    public static void Main()
    {
        bool flag = true;
        try
        {
            IConvertible conv = flag;
            Char ch = conv.ToChar(null);
            Console.WriteLine("Conversion succeeded.");
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Cannot convert a Boolean to a Char.");
        }

        try
        {
            Char ch = Convert.ToChar(flag);
            Console.WriteLine("Conversion succeeded.");
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Cannot convert a Boolean to a Char.");
        }
    }
}
// The example displays the following output:
//       Cannot convert a Boolean to a Char.
//       Cannot convert a Boolean to a Char.
open System

let flag = true
try
    let conv: IConvertible = flag
    let ch = conv.ToChar null
    printfn "Conversion succeeded."
with :? InvalidCastException ->
    printfn "Cannot convert a Boolean to a Char."

try
    let ch = Convert.ToChar flag
    printfn "Conversion succeeded."
with :? InvalidCastException ->
    printfn "Cannot convert a Boolean to a Char."

// The example displays the following output:
//       Cannot convert a Boolean to a Char.
//       Cannot convert a Boolean to a Char.
Module Example2
    Public Sub Main()
        Dim flag As Boolean = True
        Try
            Dim conv As IConvertible = flag
            Dim ch As Char = conv.ToChar(Nothing)
            Console.WriteLine("Conversion succeeded.")
        Catch e As InvalidCastException
            Console.WriteLine("Cannot convert a Boolean to a Char.")
        End Try

        Try
            Dim ch As Char = Convert.ToChar(flag)
            Console.WriteLine("Conversion succeeded.")
        Catch e As InvalidCastException
            Console.WriteLine("Cannot convert a Boolean to a Char.")
        End Try
    End Sub
End Module
' The example displays the following output:
'       Cannot convert a Boolean to a Char.
'       Cannot convert a Boolean to a Char.

변환이 지원되지 않으므로 해결 방법이 없습니다.

Convert.ChangeType 메서드

메서드를 Convert.ChangeType 호출하여 개체를 한 형식에서 다른 형식으로 변환했지만 하나 또는 두 형식 모두 인터페이스를 IConvertible 구현하지 않습니다.

대부분의 경우 변환이 지원되지 않으므로 해결 방법이 없습니다. 경우에 따라 가능한 해결 방법은 원본 형식의 속성 값을 대상 형식의 유사한 속성에 수동으로 할당하는 것입니다.

축소 변환 및 IConvertible 구현

축소 연산자는 형식에서 지원하는 명시적 변환을 정의합니다. 변환을 수행하려면 C#의 캐스팅 연산자 또는 CType Visual Basic의 변환 메서드(있는 경우 Option Strict )가 필요합니다.

그러나 원본 형식이나 대상 형식이 두 형식 간의 명시적 또는 축소 변환을 정의하지 않고 하나 또는 두 형식 IConvertible 의 구현이 원본 형식에서 대상 형식 InvalidCastException 으로의 변환을 지원하지 않는 경우 예외가 throw됩니다.

대부분의 경우 변환이 지원되지 않으므로 해결 방법이 없습니다.

다운캐스팅

다운캐스트는 기본 형식의 인스턴스를 파생 형식 중 하나로 변환하려고 하는 경우를 말합니다. 다음 예제에서는 Person 개체를 PersonWithID 개체로 변환하려고 하면 실패합니다.

using System;

public class Person
{
   String _name;

   public String Name
   {
      get { return _name; }
      set { _name = value; }
   }
}

public class PersonWithId : Person
{
   String _id;

   public string Id
   {
      get { return _id; }
      set { _id = value; }
   }
}

public class Example
{
   public static void Main()
   {
      Person p = new Person();
      p.Name = "John";
      try {
         PersonWithId pid = (PersonWithId) p;
         Console.WriteLine("Conversion succeeded.");
      }
      catch (InvalidCastException) {
         Console.WriteLine("Conversion failed.");
      }

      PersonWithId pid1 = new PersonWithId();
      pid1.Name = "John";
      pid1.Id = "246";
      Person p1 = pid1;
      try {
         PersonWithId pid1a = (PersonWithId) p1;
         Console.WriteLine("Conversion succeeded.");
      }
      catch (InvalidCastException) {
         Console.WriteLine("Conversion failed.");
      }

      Person p2 = null;
      try {
         PersonWithId pid2 = (PersonWithId) p2;
         Console.WriteLine("Conversion succeeded.");
      }
      catch (InvalidCastException) {
         Console.WriteLine("Conversion failed.");
      }
   }
}
// The example displays the following output:
//       Conversion failed.
//       Conversion succeeded.
//       Conversion succeeded.
open System

type Person() =
    member val Name = String.Empty with get, set

type PersonWithId() =
    inherit Person()
    member val Id = String.Empty with get, set


let p = Person()
p.Name <- "John"
try
    let pid = p :?> PersonWithId
    printfn "Conversion succeeded."
with :? InvalidCastException ->
    printfn "Conversion failed."

let pid1 = PersonWithId()
pid1.Name <- "John"
pid1.Id <- "246"
let p1: Person = pid1
try
    let pid1a = p1 :?> PersonWithId
    printfn "Conversion succeeded."
with :? InvalidCastException ->
    printfn "Conversion failed."

// The example displays the following output:
//       Conversion failed.
//       Conversion succeeded.
Public Class Person
   Dim _name As String
   
   Public Property Name As String
      Get
         Return _name
      End Get
      Set
         _name = value
      End Set
   End Property
End Class

Public Class PersonWithID : Inherits Person
   Dim _id As String
   
   Public Property Id As String
      Get
         Return _id
      End Get
      Set
         _id = value
      End Set
   End Property
End Class

Module Example1
    Public Sub Main()
        Dim p As New Person()
        p.Name = "John"
        Try
            Dim pid As PersonWithID = CType(p, PersonWithID)
            Console.WriteLine("Conversion succeeded.")
        Catch e As InvalidCastException
            Console.WriteLine("Conversion failed.")
        End Try

        Dim pid1 As New PersonWithID()
        pid1.Name = "John"
        pid1.Id = "246"
        Dim p1 As Person = pid1

        Try
            Dim pid1a As PersonWithID = CType(p1, PersonWithID)
            Console.WriteLine("Conversion succeeded.")
        Catch e As InvalidCastException
            Console.WriteLine("Conversion failed.")
        End Try

        Dim p2 As Person = Nothing
        Try
            Dim pid2 As PersonWithID = CType(p2, PersonWithID)
            Console.WriteLine("Conversion succeeded.")
        Catch e As InvalidCastException
            Console.WriteLine("Conversion failed.")
        End Try
    End Sub
End Module
' The example displays the following output:
'       Conversion failed.
'       Conversion succeeded.
'       Conversion succeeded.

예제에서 알 수 있듯이, 다운캐스트는 Person 개체가 PersonWithId 개체에서 Person 개체로 업캐스트되는 과정에서 생성된 경우, 또는 Person 개체가 null인 경우에만 성공합니다.

인터페이스 객체에서 변환

인터페이스 개체를 해당 인터페이스를 구현하는 형식으로 변환하려고 하지만 대상 형식은 인터페이스 개체가 원래 파생된 형식의 동일한 형식 또는 기본 클래스가 아닙니다. 다음 예제에서는 InvalidCastException 개체를 IFormatProvider 개체로 변환하려고 할 때 DateTimeFormatInfo 예외를 던집니다. 변환이 실패하는 이유는 DateTimeFormatInfo 클래스가 IFormatProvider 인터페이스를 구현했지만, DateTimeFormatInfo 개체가 인터페이스 개체가 파생된 CultureInfo 클래스와 관련이 없기 때문입니다.

using System;
using System.Globalization;

public class InterfaceEx
{
    public static void Main()
    {
        var culture = CultureInfo.InvariantCulture;
        IFormatProvider provider = culture;

        DateTimeFormatInfo dt = (DateTimeFormatInfo)provider;
    }
}
// The example displays the following output:
//    Unhandled Exception: System.InvalidCastException:
//       Unable to cast object of type //System.Globalization.CultureInfo// to
//           type //System.Globalization.DateTimeFormatInfo//.
//       at Example.Main()
open System
open System.Globalization

let culture = CultureInfo.InvariantCulture
let provider: IFormatProvider = culture

let dt = provider :?> DateTimeFormatInfo

// The example displays the following output:
//    Unhandled Exception: System.InvalidCastException:
//       Unable to cast object of type //System.Globalization.CultureInfo// to
//           type //System.Globalization.DateTimeFormatInfo//.
//       at Example.main()
Imports System.Globalization

Module Example3
    Public Sub Main()
        Dim culture As CultureInfo = CultureInfo.InvariantCulture
        Dim provider As IFormatProvider = culture

        Dim dt As DateTimeFormatInfo = CType(provider, DateTimeFormatInfo)
    End Sub
End Module
' The example displays the following output:
'    Unhandled Exception: System.InvalidCastException: 
'       Unable to cast object of type 'System.Globalization.CultureInfo' to 
'           type 'System.Globalization.DateTimeFormatInfo'.
'       at Example.Main()

예외 메시지에서 알 수 있듯이 인터페이스 개체가 원래 형식의 인스턴스로 다시 변환되는 경우에만 변환이 성공합니다. 이 경우 .CultureInfo 인터페이스 개체가 원래 형식의 기본 형식 인스턴스로 변환되는 경우에도 변환이 성공합니다.

문자열 변환

C#에서 캐스팅 연산자를 사용하여 값 또는 개체를 문자열 표현으로 변환하려고 합니다. 다음 예제에서는 Char 값을 문자열로 변환하려는 시도와 정수를 문자열로 변환하려는 시도가 모두 InvalidCastException 예외를 발생시킵니다.

public class StringEx
{
    public static void Main()
    {
        object value = 12;
        // Cast throws an InvalidCastException exception.
        string s = (string)value;
    }
}
let value: obj = 12
// Cast throws an InvalidCastException exception.
let s = value :?> string

비고

Visual Basic CStr 연산자를 사용하여 기본 형식의 값을 문자열로 변환하는 데 성공합니다. 이 작업은 InvalidCastException 예외를 발생시키지 않습니다.

모든 형식의 인스턴스를 문자열 표현으로 성공적으로 변환하려면 다음 예제와 같이 해당 ToString 메서드를 호출합니다. ToString 메서드는 항상 존재합니다. 이는 ToString 메서드가 Object 클래스에 의해 정의되기 때문에, 모든 관리되는 형식에서 상속되거나 재정의됩니다.

using System;

public class ToStringEx2
{
    public static void Main()
    {
        object value = 12;
        string s = value.ToString();
        Console.WriteLine(s);
    }
}
// The example displays the following output:
//      12
let value: obj = 12
let s = value.ToString()
printfn $"{s}"
// The example displays the following output:
//      12

Visual Basic 6.0 마이그레이션

사용자 정의 이벤트를 사용자 정의 컨트롤에서 Visual Basic .NET으로 호출하여 Visual Basic 6.0 애플리케이션을 업그레이드하고 있으며 InvalidCastException " "지정된 캐스트가 유효하지 않습니다."라는 메시지와 함께 예외가 throw됩니다. 이 예외를 제거하려면 양식의 코드 줄을 변경합니다(예: Form1).

Call UserControl11_MyCustomEvent(UserControl11, New UserControl1.MyCustomEventEventArgs(5))

다음 코드 줄로 바꿉다.

Call UserControl11_MyCustomEvent(UserControl11(0), New UserControl1.MyCustomEventEventArgs(5))