System.InvalidCastException クラス

この記事では、この API のリファレンス ドキュメントへの補足的な解説を提供します。

.NET では、派生型から基本型への自動変換とその逆方向の自動変換に加えて、インターフェイスを提供する型からインターフェイス オブジェクトへの自動変換とその逆方向の自動変換がサポートされています。 また、カスタム変換をサポートするさまざまなメカニズムも含まれています。 詳細については、「.NET での型変換」を参照してください。

ある型のインスタンスから別の型への変換がサポートされていない場合、InvalidCastException 例外がスローされます。 例えばChar値をDateTime値にキャストしようとしたときにInvalidCastExceptionがスローされます。 OverflowExceptionは、キャストは正当なものですが、キャスト前の値がキャスト後の値の範囲外の場合にスローされる例外です。 InvalidCastException 例外は、開発者エラーによって発生し、try/catch ブロックで処理することはできません。 代わりに、例外の原因を排除する必要があります。

システムでサポートされている変換については、Convertクラスを参照してください。 変換先の型が変換元の型の値を格納できるが、特定の変換元の値を格納するのに十分な大きさではない場合に発生するエラーについては、OverflowException 例外を参照してください。

Note

変換元の型と変換先の型の間に変換が存在しない場合、その多くは言語コンパイラによって検出され、コンパイラ エラーが発行されます。

変換の試行によって InvalidCastException 例外がスローされる条件の一部については、以下のセクションで説明します。

明示的な参照変換を正常に実行するには、変換元の値が null であるか、変換元の引数によって参照されるオブジェクト型を暗黙の参照変換によって変換先の型に変換できる必要があります。

次の中間言語 (IL) 命令によって、InvalidCastException 例外がスローされます。

  • castclass
  • refanyval
  • unbox

InvalidCastException は HRESULT COR_E_INVALIDCAST を使用し、その値は 0x80004002 です。

インスタンスの初期プロパティ値の一覧についてはInvalidCastExceptionを参照してください、InvalidCastExceptionコンス トラクター。

プリミティブ型と IConvertible

特定の変換をサポートしないプリミティブ型の IConvertible 実装を直接または間接的に呼び出します。 たとえば、Boolean 値を Char に、または DateTime 値を Int32 に変換しようとすると、InvalidCastException 例外がスローされます。 次の例では、Boolean.IConvertible.ToCharConvert.ToChar(Boolean) の両方のメソッドを呼び出して、Boolean 値を Char に変換します。 どちらの場合も、メソッドの呼び出しによって 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# のキャスト演算子または Visual Basic の CType 変換メソッド (Option Strict がオンの場合) が必要です。

ただし、変換元の型または変換先の型のどちらでも 2 つの型の間の明示的な変換または縮小変換が定義されておらず、一方または両方の型の 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 の場合にのみ成功します。

インターフェイス オブジェクトからの変換

インターフェイス オブジェクトを、そのインターフェイスを実装する型に変換しようとしていますが、変換先の型が、インターフェイス オブジェクトの派生元の型と同じ型、またはその基底クラスではありません。 次の例では、IFormatProvider オブジェクトを DateTimeFormatInfo オブジェクトを変換しようとすると、InvalidCastException 例外がスローされます。 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

Note

Visual Basic の CStr 演算子を使用してプリミティブ型の値を文字列に変換すると成功します。 この演算子によって InvalidCastException 例外はスローされません。

任意の型のインスタンスをその文字列表現に正常に変換するには、次の例のように ToString メソッドを呼び出します。 ToString メソッドは Object クラスで定義されるため、すべてのマネージド型によって継承またはオーバーライドされます。このため、ToString メソッドは常に存在します。

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