[英]How can an object be accessed that inherits from a generic class?
這讓我很頭疼,我希望有人願意找到解決辦法。 右下方是情況的簡化代碼。 這里的目的是,我想要一個單獨的,可重用的庫,並可以選擇為每個實現自定義這些類。 所以我去繼承:
namespace Library {
//a class that holds stuff together
public class Core<THandler> where THandler:Handler
{
public THandler handler;
public string text = "Something";
}
//class that react for extern events, say a keyboard events
public class Handler
{
protected object core;
public Handler(object _core) {
core = _core;
}
protected virtual void OnEvent() {
//how to access 'core.text' ??
var a = (Core<Handler>)core; //raises System.InvalidCastException
// since 'core' actualy contains
// an instance of MyCore
}
}
}
namespace MyImplementation {
public class MyCore : Library.Core<MyHandler>
{
}
public class MyHandler : Library.Handler
{
protected override void OnEvent() {
base.OnEvent();
//and what's the preferable option for accessing 'core' here?
var a = (MyCore)core; //I use this
}
}
}
由於Handler.core包含MyCore的一個實例,因此如何在Hanlder.OnEventmethod中訪問此對象?
最好的方法(無論如何,在我看來)是為需要在Core
訪問的方法和屬性創建一個接口。
例如,類似於以下內容:
namespace Library {
public interface ICore {
string text {get; set;}
}
//a class that holds stuff together
public class Core<THandler> : ICore where THandler : Handler
{
public THandler handler;
private string m_Text = "Something";
public string text
{
get
{
return m_Text;
}
set
{
m_Text = value;
}
}
}
//class that react for extern events, say a keyboard events
public class Handler
{
protected ICore core;
public Handler(object _core) {
core = (ICore)_core;
}
protected virtual void OnEvent() {
Debug.WriteLine(core.text);
}
}
}
namespace MyImplementation {
public class MyCore : Library.Core<MyHandler>
{
}
public class MyHandler : Library.Handler
{
protected override void OnEvent() {
base.OnEvent();
//and what's the preferable option for accessing 'core' here?
var a = (MyCore)core; //I use this
}
}
}
使用接口將Core
和Handler
相互綁定會更好。 您仍然可以保持Core<T>
通用。 泛型類型約束不允許您聲明循環依賴關系,否則就必須進行核心工作。
請注意,有問題的MyCore
無效的根本原因不是您的示例中的core
實例是MyCore
,而是因為MyCore
繼承自Core<MyHandler>
而不是Core<Handler>
。
如果由於某種原因,您堅持要保持當前的設計,則也可以使Handler
通用,將其祖先作為類型參數傳入,並像下面這樣修復類型轉換:
public class Handler<THandler> where THandler : Handler<THandler>
{
protected object core;
public Handler(object _core) {
core = _core;
}
public virtual void OnEvent() {
// this works
var a = (Core<THandler>)core;
}
}
因此,為了使其更具類型安全性並避免強制轉換,構造函數應如下所示:
protected Core<THandler> core;
public Handler(Core<THandler> _core) {
core = _core;
}
然后,很自然地, MyHandler
聲明將如下所示:
public class MyHandler : Handler<MyHandler>
{
…
}
強制轉換失敗,因為Core不協變。 一般而言,類不能協變。 只有接口和委托可以是協變的。
為了達到預期的行為,您可以將Core類定義為帶有out參數的接口,如下所示
public interface ICore<out T>where T:Handler
{
T Handler {get;}
string Text { get; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.