簡體   English   中英

如何訪問從通用類繼承的對象?

[英]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
      }
   }
}

使用接口將CoreHandler相互綁定會更好。 您仍然可以保持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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM