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.ToChar と Convert.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))
.NET