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

tes*_*est 1 c# inheritance

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

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

public class ItemExtended : Item
{
    public int ExtendedProp { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

public Item[] GetItems();
Run Code Online (Sandbox Code Playgroud)

我怎么能像这样运行代码?

ItemExtended[] itemsExt = GetItems().Cast(i => (ExtendedItem)i).ToArray();
Run Code Online (Sandbox Code Playgroud)

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

编辑(希望清除一些混乱)

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

Ryt*_*mis 5

如果对象的运行时类型是Item,则不能将其强制转换ItemExtended- 除非用户定义的转换可以创建ItemExtended一个Item.但请注意,即使这样,您也将创建一个新实例ItemExtended.

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

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

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

您可能还会觉得有趣的是,在XAML中,附加属性的概念类似于您要执行的操作:您可以为任何内容定义任意新属性 - 但是如果您查看实现,您实际在做的是创建一个将对象映射到其关联属性值的字典,并且XAML编译器通过使标记看起来像是已将属性添加到这些对象来实现这一点.