Приведение родительского класса к дочернему классу - PullRequest
5 голосов
/ 07 марта 2012

У меня есть класс Message, который я расширил и добавил новое свойство.

class ChildMessage: Message 
{
prop...
}

При попытке добавить класс сообщения в список ChildMessage я получаю нулевую ссылку для добавленного класса.

var myChildList =new List<ChildMessage> ();
var myParentClass = new Message();
myChildList.add(myParentClass as ChildMessage)

myChildList[0] == null //Always return null 

Что не так с моим кодом? Какие есть альтернативы?

Ответы [ 4 ]

18 голосов
/ 07 марта 2012

Это потому, что истинный экземпляр Message не является ChildMessage, тогда как экземпляр ChildMessage является Message.

Если myParentClass не является на самом деле экземпляр с ChildMessage вы не можете использовать оператор приведения для принудительного приведения вперед, поскольку фактический базовый тип равен Message.

Тем не менее, для использования доступны операторы implicit и explicit.на типах, так что вы могли бы, возможно, создать тот, который принимает Message и выводит ChildMessage.

http://msdn.microsoft.com/en-us/library/85w54y0a.aspx


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

Первый вариант

Используйте шаблон декоратор / обертка, чтобы обернуть Messageвнутри ChildMessage:

class ChildMessage
{
    private Message _innerMessage;

    public ChildMessage(Message innerMessage)
    {
        _innerMessage = innerMessage;
    }
}

Затем вы открываете Message или его свойства через класс ChildMessage.

Второй параметр

Это также возможно, наследовать от Message, но когда вы хотите сделать ChildMessage из Message, вам нужно будет преобразовать его , а не разыграть его:

class ChildMessage : Message
{
    public ChildMessage(Message m)
    {
        // Instantiate properties by copying from m
    }
}
3 голосов
/ 07 марта 2012

Я думаю, вы как-то не так поняли - обычно вам может понадобиться что-то вроде:

var myList =new List<Message> ();
var myChildObject = new ChildMessage();
myList.add(myChildObject)

myList[0] as ChildMessage == null // should not return null
2 голосов
/ 07 марта 2012

Приведение к объекту нельзя использовать для изменения его типа: это не преобразование .Он только сообщает тип объекта: вы объясняете, что хотите использовать объект в качестве объекта этого типа;и объект уже должен быть этого типа, иначе вы получите ошибку (по крайней мере, на приличном языке, таком как C #).

Приведение объектов имеет смысл, поскольку благодаря наследованию объекты могут иметь нескольковведите сразу.

В вашем коде каждый ChildMessage является Message, но Message, которые вы создаете, не ChildMessage s, поэтому пытаться использовать их как таковые не получается.

В отличие от этого, «приведение», скажем, целых чисел к действительным или наоборот, может фактически быть преобразованием.(Терминология в IT - безнадежные джунгли.)

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

Если вы измените свой код таким образом

var myChildList =new List<Message> (); 
var myChildClass = new ChildMessage(); 
myChildList.add(myChildClass as Message) 

Теперь у вас есть список, в котором объекты имеют тип ChildMessage или другие типы, производные от Message.Вы можете проверить правильный тип позже, когда будете использовать объекты, хранящиеся в списке.

...