c#抽象泛型:不能隐式转换type 'A: B'& # 39; b # 39;
本文关键字:type 泛型 抽象 不能 转换 | 更新日期: 2023-09-27 18:05:48
我可能需要一些帮助来获得这个编译。我只是想传递一个类类型(SuccessEventArgs
)作为一个泛型类DebugEvent<TArgs> where TArgs : System.EventArgs
的参数,但由于某种原因,这将不工作。
namespace MyInterface
{
[Serializable]
public class SuccessEventArgs : System.EventArgs
{
public SuccessEventArgs(string data);
public byte[] GetData();
}
}
public class DebugEvent<TArgs> where TArgs : System.EventArgs
{
// ...
}
// ///////////////////////////////////////////////////////////////////////
public abstract class DebugEventHandler
{
protected DebugEvent<EventArgs> m_programmingSucceededEvent = null;
}
public class MyDebugEventHandler : DebugEventHandler
{
override public void InitializeEventHandler(int programmingSuccessCode, int breakepointReachedCode)
{
m_programmingSucceededEvent = new DebugEvent<SuccessEventArgs>(ref m_eventSignal, programmingSuccessCode, this);
}
}
错误信息:
Cannot implicitly convert type 'DebugEvent<SuccessEventArgs>' to 'DebugEvent<System.EventArgs>'
这难道不可能吗?
你想要的被称为协方差。它有一些限制:
- 只有接口可以使用协方差,而不是类
- 泛型类型参数只有在不用于任何方法的输入时才能成为协变的。所以它只能在属性和方法的返回值中使用。
可以这样定义协变接口:
public interface IDebugEvent<out TArgs> where TArgs : System.EventArgs
但是注意,如果你有一个接受TArgs
类型参数的方法,这将无法编译。要想出为什么允许这样做会破坏类型安全的例子相对简单(例如,请参阅Jon Skeet对这个问题的回答)。如果这是您的需求,您将不得不重新考虑您的设计。
为了实际使用它,您必须使用接口类型的变量,而不是具体的类。你可以输入:
IDebugEvent<EventArgs> m_programmingSucceededEvent = new DebugEvent<SuccessEventArgs>();
但不是:
DebugEvent<EventArgs> m_programmingSucceededEvent = new DebugEvent<SuccessEventArgs>();
添加IDebugEvent<out T> where T : EventArgs
接口,并有DebugEvent<T> : IDebugEvent<T> where T : EventArgs
那么下面的语句就可以了:
IDebugEvent<EventArgs> m_programmingSucceededEvent = new DebugEvent<SuccessEventArgs>(ref m_eventSignal, programmingSuccessCode, this);
您需要通过为TArgs
泛型参数指定out
关键字来创建一个协变接口来实现这一点:
public interface IDebugEvent<out TArgs> where TArgs : System.EventArgs
{ /* ... */ }
这只在接口上支持,所以你需要让你的DebugEvent
类实现协变接口:
public class DebugEvent<TArgs> : IDebugEvent<TArgs> where TArgs:System.EventArgs
{ /* ... */ }
这将允许您分配一个类型的实例,该类型的泛型参数类型派生自基本System.EventArgs
类型。
IDebugEvent<EventArgs> evt = new DebugEvent<SuccessEventArgs>();