[英]Can a Base Class Method return the type of the derived class?
根據我讀過的其他帖子,這似乎是不可能的,但我想我會發布我想要做的事情,看看是否有人知道解決方案。
我正在嘗試向從 Telerik 開放訪問域模型生成的類添加“Clone()”方法。 沒問題。 我能夠弄清楚如何將基類添加到生成的實體模型中,以便我可以通過它們的基類來識別這些類。 ( 所有實體都繼承自基類)
我希望所有這些實體模型類都能夠自我克隆。 我也為此找到了解決方案。 ( 深度克隆對象)
現在我有一個基類,我想向從該基類派生的每個類添加一個 Clone() 函數。 所以......似乎基類是放置它的自然場所......對嗎?
public abstract class DBEntityBase
{
/// <summary>
/// Gets a COPY of the instance in it's current state
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
protected T Clone<T>()
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(this));
}
}
我添加了受保護的泛型 Clone()方法,因為在基類級別我們不知道要克隆的類型。 Clone() 方法需要由實體模型本身實現,以提供被克隆的特定類型。
public partial class DeliverableEntity
{
public new DeliverableEntity Clone()
{
return this.Clone<DeliverableEntity>();
}
}
這工作正常,但不能保證派生類會公開公開 Clone() 方法,因此我向基類添加了一個抽象 Clone()方法,這將要求派生類實現公共 Clone() 方法。
public abstract class DarkRoomDBEntityBase
{
/// <summary>
/// Gets a COPY of the instance in it's current state
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
protected T Clone<T>()
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(this));
}
/// <summary>
/// Gets a deep COPY of the entity instance
/// </summary>
/// <returns></returns>
public abstract DBEntityBase Clone();
}
我給它一個基類本身的返回類型; 每個實現都必須返回一個符合 DBEntityBase 的值,當然,所有派生類都這樣做。 由於 Clone() 方法正在返回派生類本身的類型,因此......這似乎是有道理的。
DeliverableEntity originalEntity = new DeliverableEntity();
DeliverableEntity clonedEntity = originalEntity.Clone();
但是,在構建時,我收到錯誤..
'DeliverableEntity' 沒有實現繼承的抽象成員 'DBEntityBase.Clone()'
大概是由於返回類型。
我知道我可以將 Clone() 方法放在一個單獨的實用程序類中,而不是直接在每個實體模型中實現它......這會讓我解決我的問題(並且可能會節省很多實現代碼),但我是仍然想知道為什么這行不通。 似乎應該有辦法做到這一點。
更新
為了回應@Luann 的第一個回復(謝謝),我將更改為“覆蓋”......
public partial class DeliverableEntity
{
public override DeliverableEntity Clone()
{
return this.Clone<DeliverableEntity>();
}
}
現在收到以下錯誤...
返回類型必須是“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<T>(this T entity) where T: DBEntityBase
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(entity));
}
}
}
一些注意事項...
現在很酷的部分是所有實體都可以訪問該功能......
// 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<T>(this T obj) where T : DBEntityBase
{
return /* insert code that creates clone here */
}
老實說,我認為這行不通,因為我預計 C# 將無法准確確定它是什么擴展。 然而,顯然,它確實如此!
新的 C# 版本 9.0 將支持協變返回,這意味着您可以覆蓋Clone()
並返回更具體的類型。 這將編譯:
public partial class DeliverableEntity
{
public override DeliverableEntity Clone()
{
return this.Clone<DeliverableEntity>();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.