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 nullzdrojová 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 PersonPersonWithID 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 PersonWithIdPerson 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))