#c# #exception #casting
Вопрос:
public class A
{
public void M1()
{
Console.Write("Print M1 of Class A");
}
}
public class B:A
{
public void M2()
{
Console.Write("Print M2 of Class B");
}
}
public class C : B
{
public void M3()
{
Console.Write("Print M3 of Class C");
}
}
В основном методе мы создаем такие объекты, как:-
A objA = new B();
B objB = new C();
A a = new A();
C objC = (C)a; /* this line throws runtime error System.InvalidCastException: 'Unable to cast object of type 'A' to type 'C'.' but build works fine */
objA.M1();
objB.M1();
objB.M2();
objC.M1();
objC.M2();
objC.M3();
Я не мог сначала привести C к A напрямую. Поэтому попытался создать объект A, а затем явным образом привел его. Intellisense воспринимает его как допустимый код, и сборка также в порядке, но во время выполнения консольного приложения он выдает ошибку «Невозможно привести объект типа»A» к типу «C»».
Комментарии:
1. Да,
a
имеет ( базовый ) типA
и не может быть приведено кC
, такC
как является производным отA
. Возможно обратное: объектc
производного классаC
может быть приведен к базовому классуA
:C c = new C(); A objA = (A) c;
2. Приведения между ссылочными типами в одном и том же дереве наследования: «эта переменная говорит , что это
x
так, но я знаю, что это действительноy
так, поверьте мне, компилятор, я знаю лучше вас». Он не преобразует anx
в ay
, вы, программист, утверждаете, что он всегда был ay
(или чем-то еще более производным).
Ответ №1:
Это правда; вы можете привести C к A в любое удобное для вас время, но единственный раз, когда вы можете сделать это наоборот, — это если вы сохранили C в переменной, набранной как A. Компилятор позволяет вам сделать это, потому что C происходит от A, поэтому переменная типа A способна содержать экземпляр типа C. Следовательно, вы могли бы законно сохранить C в A, и вы пытаетесь вернуть его в C:
A reallyC = new C();
C gotBack = (C)reallyC;
Компилятор не слишком внимательно смотрит на то, что вы делали раньше; он не увидел бы такого кода:
A reallyA = new A();
C willFail = (C)reallyA;
и скажите: «Эй, вы действительно сохранили букву «А», и ее нельзя привести к букве «С»». Он просто видит, как вы пытаетесь привести действительно к C, и думает: «Это может быть C, потому что C-это B-это A, так что они связаны нормально.. Я верю, что разработчик знает, что они делают, и я разрешу это»
Комментарии:
1. Он компилируется, но это не значит, что он правильный. Это яркий тому пример. Очень часто встречается буква » С «в букве «А». Посмотрите на обработчики событий. Первый параметр-отправитель, который относится к типу object. Очевидно, что вам почти всегда придется использовать его, чтобы использовать.
2. Хороший момент: все постоянно пишут код, который отлично компилируется, но не подходит . «Сделай это, сделай это, сделай это правильно» — часть «сделай это правильно» называется «исправление ошибок». О, а потом сделай это быстро. 😀
Ответ №2:
Ну, a
имеет (базовый) тип A
и не может быть приведен к C
, так C
как является производным от A
. Возможно обратное: объект c
производного класса C
может быть приведен к базовому классу A
:
C c = new C();
A objA = (A) c;
Часто мы можем попытаться бросить с помощью is
:
if (a is C objC) {
// a can be cast to C, objC now holds the result of the cast
objC.M3();
}
else {
// the cast is impossible
}