Kelas System.InvalidCastException

Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.

.NET mendukung konversi otomatis dari jenis turunan ke jenis dasarnya dan kembali ke jenis turunan, serta dari jenis yang menyajikan antarmuka ke objek antarmuka dan kembali. Ini juga mencakup berbagai mekanisme yang mendukung konversi kustom. Untuk informasi selengkapnya, lihat Konversi Jenis di .NET.

Pengecualian InvalidCastException dilemparkan ketika konversi instans dari satu jenis ke jenis lain tidak didukung. Misalnya, mencoba mengonversi Char nilai menjadi DateTime nilai akan melemparkan InvalidCastException pengecualian. Ini berbeda dari OverflowException pengecualian, yang dilemparkan ketika konversi dari satu jenis ke jenis lainnya didukung, tetapi nilai jenis sumber berada di luar rentang jenis target. Pengecualian InvalidCastException disebabkan oleh kesalahan pengembang dan tidak boleh ditangani dalam try/catch blok. Sebaliknya, penyebab pengecualian harus dihilangkan.

Untuk informasi tentang konversi yang didukung oleh sistem, lihat Convert kelas . Untuk kesalahan yang terjadi ketika jenis tujuan dapat menyimpan nilai jenis sumber tetapi tidak cukup besar untuk menyimpan nilai sumber tertentu, lihat OverflowException pengecualiannya.

Catatan

Dalam banyak kasus, pengkompilasi bahasa Anda mendeteksi bahwa tidak ada konversi antara jenis sumber dan jenis target dan mengeluarkan kesalahan pengkompilasi.

Beberapa kondisi di mana konversi yang dicoba melempar InvalidCastException pengecualian dibahas di bagian berikut.

Agar konversi referensi eksplisit berhasil, nilai sumber harus , atau jenis objek yang dirujuk nulloleh argumen sumber harus dapat dikonversi ke jenis tujuan dengan konversi referensi implisit.

Instruksi bahasa perantara (IL) berikut memberikan InvalidCastException pengecualian:

  • castclass
  • refanyval
  • unbox

InvalidCastException menggunakan HRESULT COR_E_INVALIDCAST, yang memiliki nilai 0x80004002.

Untuk daftar nilai properti awal untuk instans InvalidCastException, lihat InvalidCastException konstruktor.

Jenis primitif dan IConvertible

Anda secara langsung atau tidak langsung memanggil implementasi jenis IConvertible primitif yang tidak mendukung konversi tertentu. Misalnya, mencoba mengonversi Boolean nilai menjadi Char atau DateTime nilai menjadi Int32 pengecualian InvalidCastException . Contoh berikut memanggil Boolean.IConvertible.ToChar metode dan Convert.ToChar(Boolean) untuk mengonversi nilai menjadi BooleanChar. Dalam kedua kasus, panggilan metode melemparkan InvalidCastException pengecualian.

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.

Karena konversi tidak didukung, tidak ada solusi.

Metode Convert.ChangeType

Anda telah memanggil Convert.ChangeType metode untuk mengonversi objek dari satu jenis ke jenis lainnya, tetapi satu atau kedua jenis tidak mengimplementasikan IConvertible antarmuka.

Dalam kebanyakan kasus, karena konversi tidak didukung, tidak ada solusi. Dalam beberapa kasus, solusi yang mungkin adalah menetapkan nilai properti secara manual dari jenis sumber ke properti serupa dari jenis target.

Mempersempit konversi dan implementasi IConvertible

Operator penyempitan menentukan konversi eksplisit yang didukung oleh jenis. Operator transmisi di C# atau CType metode konversi di Visual Basic (jika Option Strict aktif) diperlukan untuk melakukan konversi.

Namun, jika jenis sumber maupun jenis target tidak menentukan konversi eksplisit atau mempersempit antara dua jenis, dan IConvertible implementasi satu atau kedua jenis tidak mendukung konversi dari jenis sumber ke jenis target, InvalidCastException pengecualian akan dilemparkan.

Dalam kebanyakan kasus, karena konversi tidak didukung, tidak ada solusi.

Downcasting

Anda menurun, yaitu mencoba mengonversi instans jenis dasar ke salah satu jenis turunannya. Dalam contoh berikut, mencoba mengonversi Person objek menjadi PersonWithID objek gagal.

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.

Seperti yang ditunjukkan contoh, downcast hanya berhasil jika Person objek dibuat oleh upcast dari PersonWithId objek ke Person objek, atau jika Person objek adalah null.

Konversi dari objek antarmuka

Anda mencoba mengonversi objek antarmuka ke jenis yang mengimplementasikan antarmuka tersebut, tetapi jenis target bukan jenis yang sama atau kelas dasar dari jenis tempat objek antarmuka awalnya berasal. Contoh berikut melemparkan InvalidCastException pengecualian saat mencoba mengonversi IFormatProvider objek menjadi DateTimeFormatInfo objek. Konversi gagal karena meskipun DateTimeFormatInfo kelas mengimplementasikan IFormatProvider antarmuka, DateTimeFormatInfo objek tidak terkait dengan CultureInfo kelas tempat objek antarmuka diturunkan.

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()

Seperti yang ditunjukkan oleh pesan pengecualian, konversi hanya akan berhasil jika objek antarmuka dikonversi kembali ke instans jenis asli, dalam hal ini .CultureInfo Konversi juga akan berhasil jika objek antarmuka dikonversi ke instans jenis dasar dari jenis aslinya.

Konversi string

Anda mencoba mengonversi nilai atau objek ke representasi stringnya dengan menggunakan operator transmisi di C#. Dalam contoh berikut, upaya untuk melemparkan Char nilai ke string dan upaya untuk melemparkan bilangan bulat ke string melemparkan InvalidCastException pengecualian.

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

Catatan

Menggunakan operator Visual Basic CStr untuk mengonversi nilai jenis primitif menjadi string berhasil. Operasi ini tidak melemparkan InvalidCastException pengecualian.

Agar berhasil mengonversi instans jenis apa pun ke representasi stringnya, panggil metodenya ToString , seperti contoh berikut. Metode ToString ini selalu ada, karena ToString metode didefinisikan oleh Object kelas dan oleh karena itu diwariskan atau ditimpa oleh semua jenis terkelola.

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

Migrasi Visual Basic 6.0

Anda memutakhirkan aplikasi Visual Basic 6.0 dengan panggilan ke peristiwa kustom dalam kontrol pengguna ke Visual Basic .NET, dan InvalidCastException pengecualian dilemparkan dengan pesan, "Pemeran yang ditentukan tidak valid." Untuk menghilangkan pengecualian ini, ubah baris kode dalam formulir Anda (seperti Form1)

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

dan ganti dengan baris kode berikut:

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