この記事では、この API のリファレンス ドキュメントに補足的な解説を提供します。
.NET では、派生型から基本型への自動変換、派生型への変換、およびインターフェイス オブジェクトとインターフェイス オブジェクトへのインターフェイスを提供する型からの自動変換がサポートされています。 また、カスタム変換をサポートするさまざまなメカニズムも含まれています。 詳細については、「.NET での型変換」を参照してください。
InvalidCastException例外は、ある型のインスタンスから別の型への変換がサポートされていない場合にスローされます。 たとえば、 Char 値を DateTime 値に変換しようとすると、 InvalidCastException 例外がスローされます。
OverflowException例外とは異なります。これは、ある型から別の型への変換がサポートされているが、ソース型の値がターゲット型の範囲外である場合にスローされます。
InvalidCastException例外は開発者エラーによって発生し、try/catch
ブロックでは処理しないでください。 代わりに、例外の原因を排除する必要があります。
システムでサポートされる変換の詳細については、 Convert クラスを参照してください。 変換先の型がソース型の値を格納できるが、特定のソース値を格納するのに十分な大きさではない場合に発生するエラーについては、 OverflowException 例外を参照してください。
注
多くの場合、言語コンパイラは、ソース型とターゲット型の間に変換が存在しないことを検出し、コンパイラ エラーを発行します。
変換の試行によって InvalidCastException 例外がスローされる条件の一部については、次のセクションで説明します。
明示的な参照変換を成功させるには、ソース値を null
するか、ソース引数によって参照されるオブジェクト型を暗黙的な参照変換によって変換先の型に変換できる必要があります。
次の中間言語 (IL) 命令では、 InvalidCastException 例外がスローされます。
castclass
refanyval
unbox
InvalidCastException は、値が0x80004002を持つ HRESULT COR_E_INVALIDCAST
を使用します。
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
注
Visual Basic CStr
演算子を使用してプリミティブ型の値を文字列に変換すると成功します。 この操作では、 InvalidCastException 例外はスローされません。
任意の型のインスタンスを文字列形式に正常に変換するには、次の例のように、 ToString
メソッドを呼び出します。
ToString
メソッドは常に存在します。ToString メソッドはObject クラスによって定義されるため、すべてのマネージド型によって継承またはオーバーライドされます。
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