Класс System.InvalidCastException
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
.NET поддерживает автоматическое преобразование производных типов в базовые типы и обратно в производный тип, а также от типов, которые представляют интерфейсы для объектов интерфейса и обратно. Он также включает различные механизмы, поддерживающие пользовательские преобразования. Дополнительные сведения см. в разделе "Преобразование типов" в .NET.
Исключение InvalidCastException возникает, когда преобразование экземпляра одного типа в другой тип не поддерживается. Например, при попытке преобразовать Char значение в DateTime значение вызывается InvalidCastException исключение. Он отличается от OverflowException исключения, которое возникает при поддержке преобразования одного типа в другой, но значение исходного типа выходит за пределы диапазона целевого типа. Исключение InvalidCastException вызвано ошибкой разработчика и не должно обрабатываться в блоке try/catch
. Вместо этого следует устранить причину исключения.
Сведения о преобразованиях, поддерживаемых системой, см. в Convert классе. Ошибки, возникающие при хранении значений исходного типа, но недостаточно больших для хранения определенного исходного значения, см OverflowException . исключение.
Примечание.
Во многих случаях компилятор языка обнаруживает, что преобразование между исходным типом и целевым типом не существует и выдает ошибку компилятора.
Некоторые условия, при которых попытка преобразования вызывает InvalidCastException исключение, рассматриваются в следующих разделах.
Чтобы явное преобразование ссылок было успешно выполнено, исходное значение должно быть null
равно, или тип объекта, на который ссылается исходный аргумент, должен быть преобразован в тип назначения путем неявного преобразования ссылок.
Следующие инструкции промежуточного InvalidCastException языка (IL) вызывают исключение:
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# или CType
метод преобразования в Visual Basic (если Option Strict
он включен).
Однако если ни исходный тип, ни целевой тип не определяют явное или сужающее преобразование между двумя типами, а 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
объект или если объект являетсяnull
.Person
Преобразование из объекта интерфейса
Вы пытаетесь преобразовать объект интерфейса в тип, реализующий этот интерфейс, но целевой тип не совпадает с типом или базовым классом типа, от которого объект интерфейса был первоначально производным. В следующем примере возникает InvalidCastException исключение при попытке преобразовать IFormatProvider объект в DateTimeFormatInfo объект. Преобразование завершается ошибкой, так как, хотя 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))