我对泛型有一个协变/逆变问题。 这是我正在尝试做的代码:
在框架DLL中:
namespace framework {
public interface IBase
{
//Some code...
}
public abstract class AOverClass<T> : IBase where T : IBase
{
public AOverClass(T pObject)
{
//Some code
}
//Some code...
}
public class workerClass
{
public Dictionary<Type, Type> ObjDictionary;
public AOverClass<IBase> GetOverObj(IBase initObj){
// Get the over Obj type from a dictionary that was loaded previously
// the dictionary contains KVP of <Type, Type> then using Reflection
// to initialise a new OverObj
Type t = Dictionary[initObj.GetType()];
Type[] _typesParamsConstructor = new Type[1];
_typesParamsConstructor[0] = initObj.GetType();
Object[] _valParamsConstructor = new Object[1];
_valParamsConstructor [0] = initObj;
// BIG ISSUE HERE
return (AOverClass<IBase>)t.GetConstructor(_typesParamsConstructor).Invoke(_valParamsConstructor);
}
}
}
在引用框架DLL的应用程序中:
namespace myApp {
public class Param : framework.IBase, myApp.IOtherNeeded
{
//Some code
}
public class OverParam : framework.AOverClass<Param>
{
public OverParam(Param pObject) :base(pObject)
{
//Some code...
}
}
public class App
{
private framework.workerClass _wc;
public void Init()
{
_wc = new framework.workerClass();
_wc.ObjDictionary.Add(typeof(Param), typeof(OverParam));
}
public void Run()
{
_wc.GetOverObj(new Param());
}
}
}
workerClass抛出一个异常,它无法将OverParam
强制转换为AOverClass<IBase>
。
我该如何解决这个问题?
脚注: 没有初始化问题(即字典),我只是没有编写所有与此问题无关的代码。
答案 0 :(得分:2)
根据定义,OverParam
的实例是AOverClass<Param>
。
但是您尝试将OverParam
的实例投射到AOverClass<IBase>
。那失败了。
现在只是因为任何
Param
“是”IBase
我们能否或不能得出每一个
的结论
AOverClass<Param>
“是”AOverClass<IBase>
答案是:如果AOverClass<T>
中的T
协变 ,则可以正常运行。在当前版本的C#和.NET中,唯一可以协变的类型(在类型参数out
之前标记为T
)是接口类型和委托类型。但AOverClass<T>
是 类类型 。
另外,当我们看你的班级时:
public abstract class AOverClass<T> : IBase where T : IBase
{
public AOverClass(T pObject) // an "in" parameter of type T here! :-(
{
//Some code
}
//Some code...
}
我们发现你违反了T
。因此,即使语言允许类类型是协变的,它也不适用于您的情况。这表明您的假设存在根本性的错误。