基类方法可以返回派生类的类型吗?

基于我读过的其他post,似乎这可能是不可能的,但我想我会发布我想要做的事情,看看是否有人知道解决方案。

我正在尝试向Telerik Open Access域模型生成的类添加“Clone()”方法。 没问题。 我能够弄清楚如何将基类添加到生成的实体模型中,以便我可以通过它们的基类来识别这些类。 ( 所有实体都从基类inheritance )

我希望所有这些实体模型类能够克隆自己。 我也找到了解决方案。 ( 深度克隆对象 )

现在我有一个基类,我想在每个从该基类派生的类中添加一个Clone()函数。 所以…看起来基类是放置它的自然场所……对吗?

public abstract class DBEntityBase { ///  /// Gets a COPY of the instance in it's current state ///  ///  ///  protected T Clone() { return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(this)); } } 

我添加了受保护的genericsClone()方法,因为在基类级别我们不知道我们正在克隆的类型。 Clone()方法需要由实体模型本身实现,以便提供克隆的特定类型。

 public partial class DeliverableEntity { public new DeliverableEntity Clone() { return this.Clone(); } } 

这工作正常,但不保证派生类将公开公开Clone()方法,因此我向基础添加了一个抽象Clone()方法,这将要求派生类实现公共Clone()方法。

 public abstract class DarkRoomDBEntityBase { ///  /// Gets a COPY of the instance in it's current state ///  ///  ///  protected T Clone() { return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(this)); } ///  /// Gets a deep COPY of the entity instance ///  ///  public abstract DBEntityBase Clone(); } 

我给它一个返回类型的基类本身; 每个实现必须返回一个遵循DBEntityBase的值,当然,所有派生类都会这样做。 由于Clone()方法返回一个派生类本身的类型,然后…似乎有意义,这将工作。

 DeliverableEntity originalEntity = new DeliverableEntity(); DeliverableEntity clonedEntity = originalEntity.Clone(); 

但是,在构建时,我收到错误..

‘DeliverableEntity’没有实现inheritance的抽象成员’DBEntityBase.Clone()’

大概是由于返回类型。

我知道我可能只是将Clone()方法放在一个单独的实用程序类中,而不是直接在每个实体模型中实现它…这会让我解决我的问题(并且可能会节省大量的实现代码),但我是仍然想知道为什么这不起作用。 好像应该有办法做到这一点。

UPDATE

为了回应@Luann的第一个回复(谢谢),我做了改为“覆盖”……

 public partial class DeliverableEntity { public override DeliverableEntity Clone() { return this.Clone(); } } 

我现在收到以下错误…

返回类型必须是’DBEntityBase’才能匹配被覆盖的成员’DBEntityBase.Clone()’

感谢Flynn1179,我能够再次向前迈进。 我想我会花一点时间来记录我在这里做了什么,以备将来参考..

我没有为ORM中的每个实体模型创建一个部分类,而是实现了一个抽象方法,而是按照建议创建了一个扩展方法。

 namespace DAL { public partial class DeliverableEntity : DBEntityBase { // ... Code generated from ORM } public partial class DeliverableItemEntity : DBEntityBase { // ... Code generated from ORM } public partial class DeliverableItemAttrEntity : DBEntityBase { // ... Code generated from ORM } } namespace DAL { public static class EntityExtensionMethods { public static T Clone(this T entity) where T: DBEntityBase { return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(entity)); } } } 

有些事情需要注意……

  • 将此类放在与实体模型相同的命名空间中。 如果它位于不同的命名空间中,那么您需要添加该命名空间才能访问该方法。
  • 我将generics类型的约束定义为仅inheritanceDBEntityBase类的所有类。 由于我将所有实体模型类派生自此基类,我知道所有这些类都将公开此方法,但是任何不从此类派生的类都不具备此function。
  • 扩展方法和包含它的类必须是静态的

现在很酷的部分是所有实体都可以访问该function……

  // Create the original instances of the entities DeliverableEntity origDeliverable = new DeliverableEntity(); DeliverableItemEntity origItem = new DeliverableItemEntity(); DeliverableItemAttrEntity origItemAttr = new DeliverableItemAttrEntity(); // now here's the magic DeliverableEntity cloneDeliverable = origDeliverable.Clone(); DeliverableItemEntity cloneItem = origItem.Clone(); DeliverableItemAttrEntity cloneItemAttr = origItemAttr.Clone(); 

我喜欢这个解决方案,因为它具有基类的简单性,其中实现在一个位置定义(而我正在考虑在每个派生类中单独实现一个抽象方法),因为它与DBEntityBase类相关联,并且在同一个位置命名空间,它成为基类定义的“契约”的一部分,这意味着每当我有一个派生自DBEntityBase的类时,我都可以指望它可用。

按流行要求..

尝试扩展方法:

 public T Clone(this T obj) where T : DBEntityBase { return /* insert code that creates clone here */ } 

我必须诚实,我不认为这会起作用,因为我预计C#将无法准确确定它的扩展名。 显然,确实如此!