Richard Deeming
Person p;
объявляет новую переменную с
во время компиляции типа
Person
.
Он может содержать любой объект типа
Person
, или любого типа, производного от
Person
В результате компилятор позволит вам получить доступ только к членам, определенным на
Person
тип или его базовые типы.
p = new Student();
создает новый экземпляр
Student
класс, и хранит его в
p
переменная.
Это работает, потому что
Student
класс наследуется от
Person
класс. Один
Student
это Person
.
Переменная теперь имеет
время выполнения типа
Student
... Но ...
во время компиляции тип еще есть
Person
.
Компилятор не позволит вам получить доступ к
ID
свойство, потому что оно не определено на
Person
класс или один из его базовых классов. Компилятор понятия не имеет, каким будет тип переменной во время выполнения и будет ли она иметь
ID
собственность.
p = p as Student;
принимает значение, хранящееся в
p
, и пытается привести его к
Student
пример. Если это удастся, то значение будет помещено обратно в переменную
p
. Если это не удается, переменная
p
будет установлено значение
null
.
Но тип времени компиляции
p
не измениться. Вы все еще не можете получить доступ к
ID
свойство, потому что компилятор понятия не имеет, существует ли оно вообще.
Есть различные способы получить доступ к собственности:
Student s = p as Student;
int id = s == null ? 0 : s.ID;
int id = (p as Student)?.ID ?? 0; // Shorter version of the previous code.
int id = ((Student)p).ID; // Throws an exception if p is not a Student.
dynamic d = p;
int id = d.ID; // Throws an exception if p does not have a public readable
// "ID" property that can be converted to an int.
// Also much slower than the other options.