다음을 통해 공유


System.InvalidCastException 클래스

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

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

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

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

참고 항목

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

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

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

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

  • castclass
  • refanyval
  • unbox

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

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

기본 형식 및 IConvertible

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

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됩니다.

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

다운캐스팅

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

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 가 있는 경우에만 PersonPerson 다운캐스트 PersonWithIdnull성공합니다.

인터페이스 개체에서 변환

인터페이스 개체를 해당 인터페이스를 구현하는 형식으로 변환하려고 하지만 대상 형식은 인터페이스 개체가 원래 파생된 형식의 동일한 형식 또는 기본 클래스가 아닙니다. 다음 예제에서는 개체를 InvalidCastException 개체로 변환하려고 할 때 예외를 IFormatProviderDateTimeFormatInfo throw합니다. 클래스가 인터페이스를 DateTimeFormatInfoIFormatProvider 구현하지만 개체가 인터페이스 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 throw합니다.

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 throw하지 않습니다.

모든 형식의 인스턴스를 문자열 표현으로 성공적으로 변환하려면 다음 예제와 같이 해당 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))