将父类转换为子类

5
我有一个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个回答

20
这是因为真正的Message实例并不是ChildMessage,而ChildMessage的实例则是Message

除非myParentClass实际上是用ChildMessage实例化的,否则您无法使用强制转换操作符进行前向转换,因为实际底层类型是Message

话虽如此,类型上可用的隐式和显式转换操作符,因此你可以创建一个将Message作为输入并输出ChildMessage的转换操作符。

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


如果你必须使用这些类型,并且没有其他选择来扩展该类型,则有两个选项。

第一种选择

使用装饰器/包装器模式来在一个ChildMessage中包装一个Message

class ChildMessage
{
    private Message _innerMessage;

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

你可以通过ChildMessage类来暴露Message或其属性。

第二种选择

这同样可行,继承自Message,但是当你想从Message创建一个ChildMessage时,你需要转换它,而不是强制转换:

class ChildMessage : Message
{
    public ChildMessage(Message m)
    {
        // Instantiate properties by copying from m
    }
}

好的,我该如何解决这个问题?我需要扩展父类并添加几个新属性,然后将新的父类添加到扩展类中。 - Tomas
@reinierpost 我并不是说“继承通过创建父类来实现”,我是在说继承的一个常见例子是使用它们的共同基类型来实现一些共同的行为,以此来处理许多派生类型。 - Adam Houldsworth
啊,我明白了 - 是的,在你仍在设计类和层次结构尚未因其他代码而被固定之前,这可能是可行的。我个人不太喜欢继承。 - reinierpost

3

我觉得你可能误解了 - 通常你可能想要这样的内容:

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

myList[0] as ChildMessage == null // should not return null

2
如果你按照以下方式修改你的代码:
var myChildList =new List<Message> (); 
var myChildClass = new ChildMessage(); 
myChildList.add(myChildClass as Message) 

现在您有一个List,其中的对象是ChildMessage类型或其他继承自Message的类型。稍后在使用存储在列表中的对象时,您可以检查正确的类型。

我需要将Message类添加到List中。我从一个对象中获取Message类并需要将其存储到扩展的Message类中。 - Tomas
我现在有些困惑。如果类B继承自类A,而类C也继承自A,那么你可以将A、B和C的所有实例存储在List<A>中。当然,在从List<A>检索元素时,你需要一种机制来知道对象的确切类型。在C#中,这可以通过多种方式完成(查找关键字“as”、“is”和“typeof”)。 - Steve
我有一个类A,我通过另一个对象获取它作为新实例。我需要将其存储到List<B>中,其中B:A。如何将A转换为B? - Tomas
A的实例不是B的实例,B的实例也是A的实例。请参见更详细的@Adam Houldsworth答案。 - Steve

2
在对象上执行强制类型转换无法用于更改对象的类型:它不是一种转换。它只用于告诉对象的类型:您解释了想要将对象用作该类型的对象;对象必须已经属于该类型,否则会出现错误(至少在像C#这样的良好语言中)。
强制类型转换是有意义的,因为由于继承关系,对象可以同时属于多种类型。
在您的代码中,每个ChildMessage都是一个Message,但您创建的Message并不是ChildMessage,因此尝试将其用作ChildMessage会失败。
相比之下,从整数到实数或反之间的“强制转换”可能实际上是一种转换。(IT术语不堪设想。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接