C#类及其子类怎么作为泛型传递 20
在C#里,普通类和抽象类不支持【协变】,想要用协变得用【接口】。
所谓【协变】,比如有接口IA,及其子类AA
IA<BaseQueryInfo> a=new AA<MultiBorrowTag>(...) //OK,正确的协变。
AA<BaseQueryInfo> a=new AA<MultiBorrowTag>(...) //错误,不允许协变!
协变接口的定义:
interface IA<out T> //这个out很重要,表示这个接口支持协变。
{
void F(); //OK
T G();//OK,协变允许泛型形参作为返回值。
void H(T t);//错误,协变不允许泛型形参作为函数形参。
}
所以,解决方案一:在声明DataTagEnumQueryDict变量时,用DataProcessEntity的【声明了out的父接口】代替。比如假定有个接口IDataProcess<out T>
则声明为:
private static Dictionary<DataTagEnum, IDataProcess<BaseQueryInfo>> DataTagEnumQueryDict = new ...
解决方案二:
如果类DataProcessEntity压根不存在声明了out的父接口怎么办?没办法,只能都new DataProcessEntity<BaseQueryInfo> {...}
解决方案三:如果你又不想new DataProcessEntity<BaseQueryInfo> {...},怎么办?也有一种比较曲折的方法:
自己定义一个接口!
interface IDataProcessEntityDelegator<out T>
{
void AAA();//把想要用的DataProcessEntity的方法签名原样抄下来,但千万不要抄将T用作方法形参的。
T BBB();
....
}
再定义
class DataProcessEntityDelegator<T>
{
private readonly DataProcessEntity entity;
public DataProcessEntityDelegator<out T>(A a, B b, C c.....)
{
entity=new DataProcessEntity(a,b,c.....);
}
public void AAA() =>entity.AAA();
public T BBB() = > entity.BBB();//注:这是C#6.0以后的简写语法,否则自己写完整的函数体。
}
然后你就可以快乐的在代码里写:
private static Dictionary<DataTagEnum, IDataProcessEntityDelegator<BaseQueryInfo>> DataTagEnumQueryDict = new ...
......
DataTagEnumQueryDict.Add(... ,DataProcessEntityDelegator<BaseQueryInfo>{......} );
DataTagEnumQueryDict.Add(... ,DataProcessEntityDelegator<MultiBorrowTag>{......} );
DataTagEnumQueryDict.Add(... ,DataProcessEntityDelegator<BlackListTag>{......} );
用哪种方法就看你的觉悟了
测试了一下第3、4行,好像没有问题啊,可以正常使用
没道理啊,普通类是不能支持协变和逆变,只有接口和委托可以拥有可变的类型参数。你测试的是具体哪一句啊?