本文提供此 API 參考文件的補充備註。
.NET 支援從衍生型別到基底型別的自動轉換以及返回至衍生型別,同時支援從實作介面的類型到介面物件,以及返回至此類型的轉換。 它也包含各種支援自定義轉換的機制。 如需詳細資訊,請參閱 .NET 中的類型轉換。
當不支援將某型別的實例轉換為另一型別時,就會擲回例外狀況。 例如,嘗試將Char值轉換成DateTime值時,會引發InvalidCastException例外。 這與 OverflowException 例外狀況不同,當支援將某個類型轉換成另一種類型時,就會擲回例外狀況,但來源類型的值超出目標類型的範圍。 例外 InvalidCastException 是由開發人員錯誤所造成的,不應在 try/catch 區塊中處理。 相反地,應該排除例外狀況的原因。
如需系統所支援轉換的相關信息,請參閱 類別 Convert 。 如需瞭解當目標型別可以儲存來源型別值但不足以儲存特定來源值時所發生的錯誤,請參閱 OverflowException 例外狀況。
備註
在許多情況下,您的語言編譯程式會偵測來源類型與目標類型之間沒有轉換,併發出編譯程序錯誤。
下列各節將討論嘗試轉換時會擲 InvalidCastException 例外狀況的某些情況。
若要讓明確參考轉換成功,來源值必須是 null,或者來源自變數所參考的物件類型必須可透過隱含參考轉換轉換為目的地類型。
下列中繼語言(IL)指令會引發InvalidCastException例外狀況:
castclassrefanyvalunbox
InvalidCastException 會使用具有 值0x80004002的 HRESULT COR_E_INVALIDCAST。
如需查看 InvalidCastException 實例的初始屬性值列表,請參閱 InvalidCastException 的建構子。
基本類型與 IConvertible
您直接或間接呼叫基本類型的IConvertible實作,而該實作不支援特定的轉換。 例如,嘗試將Boolean值轉換為Char值,或將DateTime值轉換為Int32值會拋出InvalidCastException例外狀況。 下列範例會呼叫 Boolean.IConvertible.ToChar 和 Convert.ToChar(Boolean) 方法,將值Boolean轉換成 Char 。 在這兩種情況下,方法呼叫都會丟出例外狀況。
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# 中的轉型運算子或 Visual Basic 中的 CType 轉換方法(在 Option Strict 開啟的情況下)必須用於執行轉換。
不過,如果來源類型或目標類型都未定義這兩種類型之間的明確或縮小轉換,而 IConvertible 一或兩種類型的實作都不支援從來源類型轉換成目標類型, InvalidCastException 則會擲回例外狀況。
在大部分情況下,因為不支持轉換,因此沒有因應措施。
向下轉型
您正在進行向下類型轉換,也就是嘗試將基底類型的實例轉換成其中一個衍生型別。 在下列範例中,嘗試將對象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 類別無關,而 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 6.0 應用程式升級至 Visual Basic .NET,並出現例外狀況InvalidCastException,訊息為:「指定的轉換無效」。若要消除此例外狀況,請變更您表單中的程式代碼行(例如Form1)。
Call UserControl11_MyCustomEvent(UserControl11, New UserControl1.MyCustomEventEventArgs(5))
並將它取代為下列程式碼:
Call UserControl11_MyCustomEvent(UserControl11(0), New UserControl1.MyCustomEventEventArgs(5))