Что вам нужно понять, так это то, что кастинг никоим образом не изменяет базовый объект.
Так что, если у меня есть эти классы:
public class Animal { }
public class Dog : Animal { }
... и я пишу этот код:
Dog d = new Dog();
Animal a = (Animal)d;
Переменная a
еще Dog
, это просто время действующие как если бы были только Animal
.
Если я определил этот класс:
public class Cat : Animal { }
... и я попытался затем написать этот код:
Dog d = new Dog();
Cat c = (Cat)d;
... Я получаю сообщение об ошибке, но не потому, что я могу» t изменить a Dog
на Cat
, а потому, что объект d
всегда Dog
, и я не могу лечить его, как если бы это был Cat
. A Dog
никогда не может быть Cat
.
Так что в вашем коде, когда вы пишете:
A a = new A();
B b = (B)a;//SystemCastInvalidException
... то же самое - это A
никогда не может быть B
.
Но в вашем коде a B
может быть A
.
Так что, если я переписывать код немного, как это:
B bCanDo = new B();
bCanDo.Children.Add(new B());
foreach (A a in bCanDo.Children)
{
B notExpected = (B)a;
}
... вы можете увидеть, что даже несмотря на то, Children
из bCanDo
являются тип A
вы можете добавить детей типа B
- в B
может быть A
. Поэтому, когда вы перебираете Children
, типы детей никогда не меняются так, хотя члены Children
- A
, если добавлен B
, вы всегда можете вернуть его обратно на B
. Вот почему работает литье foreach
.
Я предполагаю, что вы используете 'foreach (var c in b.Children)', не так ли? – HimBromBeere
Разница заключается в том, что 'c' фактически * is * типа' B', а 'a' имеет тип' A'. – Corak
Вы должны немного очистить свой пример, я предполагаю, что 'bCanDo' является переменной типа' A' или что она должна быть 'b'? –