System.InvalidCastException 類別

本文提供此 API 參考文件的補充備註。

.NET 支援從衍生型別自動轉換成基底型別,以及從呈現介面物件和返回介面之介面的類型。 它也包含各種支援自定義轉換的機制。 如需詳細資訊,請參閱 .NET 中的類型轉換。

InvalidCastException不支援將某個型別的實例轉換成另一個型別時,就會擲回例外狀況。 例如,嘗試將值轉換成 CharDateTimeInvalidCastException 擲回例外狀況。 這與 OverflowException 例外狀況不同,當支援將某個類型轉換成另一種類型時,就會擲回例外狀況,但來源類型的值超出目標類型的範圍。 例外 InvalidCastException 狀況是由開發人員錯誤所造成,不應在 區塊中 try/catch 處理。 相反地,應該排除例外狀況的原因。

如需系統所支援轉換的相關信息,請參閱 類別 Convert 。 如需當目的地類型可以儲存來源類型值但不足以儲存特定來源值時所發生的錯誤,請參閱 OverflowException 例外狀況。

注意

在許多情況下,您的語言編譯程式會偵測來源類型與目標類型之間沒有轉換,併發出編譯程序錯誤。

下列各節將討論嘗試轉換擲 InvalidCastException 回例外狀況的一些情況。

若要讓明確參考轉換成功,來源值必須是 null,或者來源自變數所參考的物件類型必須可透過隱含參考轉換轉換為目的地類型。

下列中繼語言 (IL) 指示會擲回 InvalidCastException 例外狀況:

  • castclass
  • refanyval
  • unbox

InvalidCastException 會使用具有 值0x80004002的 HRESULT COR_E_INVALIDCAST

如需執行個體的初始屬性值的清單InvalidCastException,請參閱InvalidCastException建構函式。

基本類型與 IConvertible

您直接或間接呼叫不支援特定轉換的基本 IConvertible 類型實作。 例如,嘗試將值Char轉換成 ,或DateTime將值Int32轉換成 Boolean 擲回例外狀況InvalidCastException。 下列範例會呼叫 Boolean.IConvertible.ToCharConvert.ToChar(Boolean) 方法,將值Char轉換成 Boolean 。 在這兩種情況下,方法呼叫都會 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 則會擲回例外狀況。

在大部分情況下,因為不支持轉換,因此沒有因應措施。

向下轉型

您正在向下轉型,也就是嘗試將基底類型的實例轉換成其中一個衍生型別。 在下列範例中,嘗試將對象PersonWithID轉換成 Person 物件會失敗。

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物件從 物件Person建立物件到 物件時,或物件為 nullPerson,下播PersonWithId才會成功。

從介面物件轉換

您嘗試將介面物件轉換成實作該介面的類型,但目標型別與原本衍生介面物件之型別的類型或基類不同。 下列範例會在嘗試將 物件轉換成 IFormatProvider 物件時擲回InvalidCastException例外狀況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 類別所定義,因此會由所有Managed型別繼承或覆寫。

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 6.0 應用程式,並在使用者控件中呼叫自定義事件至 Visual Basic .NET,並擲回例外 InvalidCastException 狀況訊息:「指定的轉換無效」。若要排除此例外狀況,請變更表單中的程式代碼行 (例如 Form1

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

並將它取代為下列程式代碼列:

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