Как явно привести типы (пользовательский класс) - PullRequest
0 голосов
/ 06 марта 2012

У меня есть следующий код, который я изучаю. Я знаю, что не могу неявно преобразовать «родителя» в «ребенка» (но я могу сделать это наоборот). Тем не менее, я пытаюсь явно конвертировать, но не могу заставить его работать. Я предполагаю, что ребенок должен потерять данные при преобразовании в родителя.

class Parent
{
    int A=5;
}

class Child:Parent
{
    int B=5;
    int C=2;
}

Parent parent = new Parent();
Child ch = new Child();

ch=ch as Parent //or (Parent)ch;

Ответы [ 7 ]

4 голосов
/ 06 марта 2012

зачем тебе это делать? Child является Parent из-за наследственных отношений. Везде, где вам нужен Parent, вы можете передать Child, и он должен работать (и если это не так, вы нарушаете Принцип замещения Лискова ).

Вы можете посмотреть на Child, как если бы это был Parent, например:

 Child ch = new Child();
 Parent childAsParent = ch as Parent;

но довольно бессмысленно ...

Разница между использованием as Parent и (Parent) заключается в том, получите ли вы ошибку или нет. «Безопасное» приведение (с использованием as) просто оставит вас с нулем, если ch не является экземпляром Parent, что в этом случае всегда будет. Другой бросит InvalidCastException , если невозможно выполнить приведение.

3 голосов
/ 06 марта 2012

ch равно a Parent, нет необходимости делать это приведение

, если вы протестируете это выражение

bool isParent = ch is Parent

, которое вы увидитечто isParent = true.Вы можете использовать ch как Parent в любом месте без использования приведения

2 голосов
/ 06 марта 2012

Вам нужно установить правильный тип при касте ...

Child ch = child as Parent; //Wrong
Child ch = (Parent)child;   //Wrong
Parent p = child as Parent; //Correct
Parent p = (Parent)child;   //Correct
var p = child as Parent;    //Correct (var will end up being a Parent)
var p = (Parent)child;      //Correct (var will end up being a Parent)

Различные типы приведений можно объяснить здесь (вопрос StackOverflow).


Я предполагаю, что ребенок должен потерять данные при преобразовании в родителя.

Это неверное предположение. Вы не « теряете » данные, но вы меняете тип, который меняет членов, к которым у вас есть доступ. Измените его обратно на Child, и члены B и C по-прежнему сохраняют свои значения.

0 голосов
/ 06 марта 2012

Обратите внимание на разницу между экземпляром объекта и ссылкой.

new Child();

создает (создает экземпляр) класс Child.Это означает, что теперь есть объект (в «куче»), но у вас нет прямого доступа к этому объекту, у вас есть косвенный доступ через ссылки на него.Как только объект создан, вы не можете изменить его тип.

Child ch;

определяет ссылку с дочерним интерфейсом, которая по умолчанию не ссылается на объект (IE: null)

Parent parent;

определяет ссылку с родительским интерфейсом.

Как только эти ссылки существуют, вы можете назначить их объектам, используя такие строки, как:

parent = new Parent();

или

ch = new Child();

Поскольку Child наследует от Parent (как уже говорили другие, это «является Parent»), ссылки Parent могут также ссылаться на объекты Child.IE:

parent = new Child();

или

parent = ch;

, но вы сможете получить доступ только к тем частям объекта Child, которые определены Parent, через ссылку Parent.Обратите внимание, что приведение не обязательно для этого.Тем не менее, вам понадобится бросок в другом направлении.То есть, если это все еще дочерний объект, но у вас пока есть только родительская ссылка, вам нужно преобразование, чтобы получить дочернюю ссылку:

ch = (Child)parent;

или

ch = parent as Child;

Первый бросит исключение, если приведение не может быть выполнено.Последний назначит ноль для ch, если приведение не может быть выполнено.

0 голосов
/ 06 марта 2012

измените ваши последние строки на

Parent castRef = ch as Parent; 
Parent castRef = (Parent)ch;

Первый - это "безопасное приведение", он проверит, является ли ch на самом деле родительским типом (или потомком), и вернет ссылку на родительский класс, еслиэто и ноль, если нет.Это идет рука об руку с оператором as (как в случае, если (ch является Parent) ...)

Последний является явным приведением и не проверяет, в основном оставляя вас со ссылкой на что-то, что не являетсяof (или происходит от Parent), который будет странным образом ошибаться при его использовании.

Я бы всегда предпочел предыдущую версию.

и явно отвечал на ваш запрос;вам нужна новая переменная родительского типа ref, чтобы назначить приведение в.

0 голосов
/ 06 марта 2012

Изменение

Parent parent = new Parentk(); 
Child ch = new Child(); 
ch=ch as Parent //or (Parent)ch; 

от

Parent parent = new Parent(); 
Child ch = new Child(); 
parent=ch as Parent //or (Parent)ch; 

Вы приводите дочерний элемент к родителю, но в результате получается дочерний объект

0 голосов
/ 06 марта 2012

Проблема в том, что ch - это Child, и вы пытаетесь присвоить ему Parent. Вы пытались заменить последнюю строку на

Parent pa = ch as Parent;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...