C# 如何访问从泛型类继承的对象?

C# 如何访问从泛型类继承的对象?,c#,generics,inheritance,C#,Generics,Inheritance,这让我头晕目眩,我希望有人能找到解决办法。 下面是情况的简化代码。这里的目标是,我需要一个单独的、可重用的库,并且可以选择为每个实现定制这些类。所以我选择了继承: 命名空间库{ //把东西放在一起的类 公共类核心,其中THandler:Handler { 公共塔德勒处理器; 公共字符串text=“某物”; } //类,该类对外部事件(如键盘事件)作出反应 公共类处理程序 { 保护对象核心; 公共处理程序(对象_核心){ 核心=_核心; } 受保护的虚拟void OnEvent(){ //如何访问

这让我头晕目眩,我希望有人能找到解决办法。 下面是情况的简化代码。这里的目标是,我需要一个单独的、可重用的库,并且可以选择为每个实现定制这些类。所以我选择了继承:

命名空间库{
//把东西放在一起的类
公共类核心,其中THandler:Handler
{
公共塔德勒处理器;
公共字符串text=“某物”;
}
//类,该类对外部事件(如键盘事件)作出反应
公共类处理程序
{
保护对象核心;
公共处理程序(对象_核心){
核心=_核心;
}
受保护的虚拟void OnEvent(){
//如何访问“core.text”??
var a=(Core)Core;//引发System.InvalidCastException
//因为“核心”实际上包含
//MyCore的一个实例
}
}
}
命名空间实现{
公共类MyCore:Library.Core
{
}
公共类MyHandler:Library.Handler
{
受保护的覆盖void OnEvent(){
base.OnEvent();
//访问“核心”的首选选项是什么?
var a=(MyCore)core;//我使用这个
}
}
}
由于Handler.core包含MyCore的实例,如何在Handler.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
      }
   }
}
命名空间库{
公共接口ICore{
字符串文本{get;set;}
}
//把东西放在一起的类
公共类核心:ICore,其中THandler:Handler
{
公共塔德勒处理器;
私有字符串m_Text=“Something”;
公共字符串文本
{
得到
{
返回m_文本;
}
设置
{
m_Text=值;
}
}
}
//类,该类对外部事件(如键盘事件)作出反应
公共类处理程序
{
保护ICore核;
公共处理程序(对象_核心){
核心=(ICore)\u核心;
}
受保护的虚拟void OnEvent(){
Debug.WriteLine(core.text);
}
}
}
命名空间实现{
公共类MyCore:Library.Core
{
}
公共类MyHandler:Library.Handler
{
受保护的覆盖void OnEvent(){
base.OnEvent();
//访问“核心”的首选选项是什么?
var a=(MyCore)core;//我使用这个
}
}
}

最好使用接口将
核心
处理程序
相互绑定。您仍然可以保留
Core
generic。泛型类型约束不允许您声明循环依赖项,否则这将是使核心工作所必需的

请注意,问题强制转换无效的根本原因不是示例中的
core
实例是
MyCore
,而是因为
MyCore
继承自
core
,而不是
core

如果出于某种原因,您坚持保持当前设计,您也可以将
处理程序
设置为泛型,将其祖先作为类型参数传入,并按如下方式修复强制转换:

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;
    }
public class MyHandler : Handler<MyHandler>
{
    …
}

该强制转换失败,因为核心不协变。类通常不能是协变的。只有接口和委托可以是协变的

为了达到预期的行为,您可以将核心类定义为带有out参数的接口,如下所示

public interface ICore<out T>where T:Handler
{
    T Handler {get;}
    string Text { get; }
}
公共接口ICorewhere T:Handler
{
T处理程序{get;}
字符串文本{get;}
}

核心是否必须是泛型类?我看不出有什么好处。如果您可以通过构造函数将处理程序注入核心,那么这将非常简单。不,当然,它不必是通用的。但是想想所有显式强制转换来访问在descendand类中定义的东西。。虽然不确定这是否是性能问题,但肯定会让代码有点混乱。好主意,不过最后这打破了我选择泛型的原因。在Handler中,它可以完美地工作,但在MyHandler中访问MyCore会使我需要转换核心字段——因为ICore无法实现我的任何东西,我将尝试一下。听起来正是我想要的!
public interface ICore<out T>where T:Handler
{
    T Handler {get;}
    string Text { get; }
}