System.InvalidCastException – třída
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
.NET podporuje automatický převod odvozených typů na jejich základní typy a zpět na odvozený typ, stejně jako z typů, které představují rozhraní na objekty rozhraní a zpět. Zahrnuje také řadu mechanismů, které podporují vlastní převody. Další informace naleznete v tématu Převod typů v .NET.
Výjimka InvalidCastException je vyvolán v případě, že převod instance jednoho typu na jiný typ není podporován. Například při pokusu Char o převod hodnoty na hodnotu dojde k DateTime výjimce InvalidCastException . Liší se od OverflowException výjimky, která se vyvolá, když je podporován převod jednoho typu na jiný, ale hodnota zdrojového typu je mimo rozsah cílového typu. Výjimka InvalidCastException je způsobená chybou vývojáře a neměla by být zpracována try/catch
v bloku. Místo toho by se měla odstranit příčina výjimky.
Informace o převodech podporovaných systémem naleznete ve Convert třídě. Chyby, ke kterým dochází, když cílový typ může ukládat hodnoty zdrojového typu, ale není dostatečně velký k uložení konkrétní zdrojové hodnoty, podívejte se na OverflowException výjimku.
Poznámka:
V mnoha případech kompilátor jazyka zjistí, že mezi zdrojovým typem a cílovým typem neexistuje žádný převod a vydává chybu kompilátoru.
Některé z podmínek, za kterých pokus o převod vyvolá InvalidCastException výjimku, jsou popsány v následujících částech.
Aby byl explicitní převod odkazu úspěšný, musí být null
zdrojová hodnota nebo typ objektu odkazovaný zdrojovým argumentem musí být převoditelný na cílový typ implicitním převodem odkazu.
Následující pokyny pro zprostředkující jazyk (IL) vyvolá InvalidCastException výjimku:
castclass
refanyval
unbox
InvalidCastException používá HODNOTU HRESULT COR_E_INVALIDCAST
, která má hodnotu 0x80004002.
Seznam počátečních hodnot vlastností pro instanci InvalidCastExceptionnaleznete v InvalidCastException konstruktorech.
Primitivní typy a IConvertible
Přímo nebo nepřímo voláte implementaci primitivního typu IConvertible , která nepodporuje konkrétní převod. Například při pokusu Boolean o převod hodnoty na Char hodnotu nebo DateTime na vyvolání Int32InvalidCastException výjimky. Následující příklad volá jak metodyBoolean.IConvertible.ToChar, tak Convert.ToChar(Boolean) i metody pro převod Boolean hodnoty na .Char V obou případech vyvolá volání InvalidCastException metody výjimku.
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.
Protože převod není podporovaný, neexistuje žádné alternativní řešení.
Metoda Convert.ChangeType
Volali jste metodu Convert.ChangeType pro převod objektu z jednoho typu na jiný, ale jeden nebo oba typy neimplementují IConvertible rozhraní.
Ve většině případů, protože převod není podporovaný, neexistuje žádné alternativní řešení. V některých případech je možným alternativním řešením ruční přiřazení hodnot vlastností ze zdrojového typu k podobným vlastnostem cílového typu.
Zužující převody a implementace IConvertible
Zužující operátory definují explicitní převody podporované typem. K provedení převodu se vyžaduje operátor přetypování v jazyce C# nebo metoda převodu CType
v jazyce Visual Basic (pokud Option Strict
je zapnutá).
Pokud však zdrojový typ ani cílový typ nedefinuje explicitní nebo zužující převod mezi těmito dvěma typy a IConvertible implementace jednoho nebo obou typů nepodporuje převod ze zdrojového typu na cílový typ, InvalidCastException vyvolá se výjimka.
Ve většině případů, protože převod není podporovaný, neexistuje žádné alternativní řešení.
Downcasting
Přetypováváte, to znamená, že se pokoušíte převést instanci základního typu na jeden z jeho odvozených typů. V následujícím příkladu se pokus o převod objektu Person
PersonWithID
na objekt nezdaří.
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.
Jak ukazuje příklad, downcast bude úspěšný pouze v případě Person
, že objekt byl vytvořen upcast z objektu PersonWithId
Person
na objekt, nebo je-li Person
objekt null
.
Převod z objektu rozhraní
Pokoušíte se převést objekt rozhraní na typ, který implementuje toto rozhraní, ale cílový typ není stejný typ nebo základní třída typu, ze kterého byl objekt rozhraní původně odvozen. Následující příklad vyvolá InvalidCastException výjimku, když se pokusí převést IFormatProvider objekt na DateTimeFormatInfo objekt. Převod selže, protože ačkoli DateTimeFormatInfo třída implementuje IFormatProvider rozhraní, objekt nesouvisí s CultureInfo třídou, DateTimeFormatInfo ze které byl objekt rozhraní odvozen.
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()
Jak zpráva o výjimce označuje, převod by byl úspěšný pouze v případě, že je objekt rozhraní převeden zpět na instanci původního typu, v tomto případě .CultureInfo Převod by také byl úspěšný, pokud je objekt rozhraní převeden na instanci základního typu původního typu.
Převody řetězců
Pokoušíte se převést hodnotu nebo objekt na řetězcovou reprezentaci pomocí operátoru přetypování v jazyce C#. V následujícím příkladu se pokus o přetypování Char hodnoty na řetězec i pokus o přetypování celého čísla na řetězec vyvolá InvalidCastException výjimku.
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
Poznámka:
Pomocí operátoru Jazyka Visual Basic CStr
převedete hodnotu primitivního typu na řetězec úspěšně. Operace nevyvolá InvalidCastException výjimku.
Chcete-li úspěšně převést instanci libovolného typu na řetězcové vyjádření, zavolejte jeho ToString
metodu, jak to dělá následující příklad. Metoda ToString
je vždy přítomna, protože ToString metoda je definována Object třídou, a proto je buď zděděna nebo přepsána všemi spravovanými typy.
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
Migrace jazyka Visual Basic 6.0
Upgradujete aplikaci jazyka Visual Basic 6.0 s voláním vlastní události v uživatelském ovládacím prvku na rozhraní .NET jazyka Visual Basic a je InvalidCastException vyvolán výjimka se zprávou Zadané přetypování není platné. Chcete-li tuto výjimku odstranit, změňte řádek kódu ve formuláři (například Form1
)
Call UserControl11_MyCustomEvent(UserControl11, New UserControl1.MyCustomEventEventArgs(5))
a nahraďte ho následujícím řádkem kódu:
Call UserControl11_MyCustomEvent(UserControl11(0), New UserControl1.MyCustomEventEventArgs(5))