如何通过继承向类添加属性,然后将基类强制转换为新类?

时间:2014-09-27 19:17:36

标签: c# inheritance

我想知道是否有办法在C#中执行此继承情况:

public class Item
{
    public string Name { get; set; }
}

public class ItemExtended : Item
{
    public int ExtendedProp { get; set; }
}

让我们说我有一个返回Item类型对象的方法:

public Item[] GetItems();

如何制作这样的代码?

ItemExtended[] itemsExt = GetItems().Cast(i => (ExtendedItem)i).ToArray();

如果演员不会失败,那么Name属性值会被保留,我还有一个我可以访问的附加属性ExtendedProp

修改(希望能够澄清一些混淆)

在这种情况下,GetItems方法只会返回Item类型的项目。我想知道是否有一个转换方法可以将基类型转换为继承类型,以便保留所有基本成员值(不使用克隆)。

3 个答案:

答案 0 :(得分:5)

如果对象的运行时类型为Item,则无法将其转换为ItemExtended - 除非有user-defined conversion可以创建ItemExtended Item。但请注意,即使这样,您也将创建ItemExtended的新实例。

一般来说,继承不起作用。在托管语言中,仅当对象的运行时类型已经是派生类型时,向下转换才有效。派生类的实例继承其祖先类的所有数据和行为,但是祖先不具有派生类的任何知识。考虑一个示例,其中派生类引入单个新字段。首先,基类实例的大小,所以至少,类型转换需要分配新的内存。其次,您必须在更改原始实例的运行时类型(确实非常奇怪)或制作旧数据的副本之间做出决定。后一种方式与用户定义的转换方案非常相似,除了明确调用用户定义的转换,以及更好的IMO方式。

在非托管语言中,您当然可以进行任何您想要的任意转换 - 但如果您做错了,这只会导致灾难性的失败。在上面的示例中,您将尝试访问新字段,但由于它不会为实例分配,因此您将超出对象的内存空间和访问的边界......无论在那里,它是否有意义或不。

如果要向现有类引入新行为,C#方式是通过extension methods。扩展属性尚未存在,也可能永远不会存在,因此您无法获得属性语法。你可能会或可能不会忍受这种情况。

您可能也觉得有趣,在XAML中,attached properties的概念适合您要做的事情:您可以为任何事物定义任意新属性 - 但如果您看起来在实现中,您真正在做的是创建一个将对象映射到其关联属性值的字典,并且XAML编译器通过使标记看起来像您已将属性添加到这些对象来实现这一点。

答案 1 :(得分:1)

您可以使用OfType代替Cast

ItemExtended[] itemsExt = GetItems().OfType<ItemExtended>().ToArray();

答案 2 :(得分:0)

你在正确的轨道上做了一些调整,

  • 使用选择()而不是 Cast()
  • 我作为ItemExtended 而不是(ItemExtended)i

此行应正确投射:

  

ItemExtended[] itemsExt = GetItems().Select(i => i as ItemExtended).ToArray();