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