只要我们谈论动物和鱼类,通用类型协方差和反演法都很清楚,但为什么不应该这样做,你能解释一下吗?
interface IType
{}
interface IGenericInterface<TType> where TType:IType
{}
class TypeImpl:IType
{}
class GenericTypeImpl : IGenericInterface<TypeImpl>
{}
class Program
{
static void Main(string[] args)
{
Convert<IGenericInterface<TypeImpl>, TypeImpl>(new GenericTypeImpl());
}
static IGenericInterface<IType> Convert<S, D> (S instance) where S:IGenericInterface<D> where D:IType
{
return (IGenericInterface<IType>)instance; //nope
}
}
确实我可以用来解决演员表,但是我不能这样做:
interface IGenericInterface<out TType> where TType:IType
{
void afunction(TType type); //nope
void afunction(IType type); //works but not nice
}
编辑:没有解决方法。我感兴趣的原因(放弃之前)是我想收集所有GenericTypeImpl
实例到集合中,然后通过泛型函数使用。显然,在一个集合中存储IType实现可能变化的IGenericInterface<IType>
的不同实现的唯一方法是使用IGenericInterface<IType>
作为集合参数,因此我需要将单个实例强制转换回原始类型并调用方法afunction
,代码类似于:
void CallSuitableAFunction<T>(T type) where T : IType
{
if (_collectedInstances.TryGetValue(typeof(T), out instance))
{
(instance as IGenericInterface<T>).afunction(); //will throw
}
}
Dictionary<Type, IGenericInterface<IType>> _collectedInstances;
答案 0 :(得分:2)
在您的类型实现中没有协方差反演。您应该使用out
进行协方差(这是您的情况),或in
进行逆转。
interface IGenericInterface<out TType> where TType:IType // notice out keyword
{}
当您使TType
协方差时,它应仅用作输出,例如仅用于TType Method()
等方法的返回类型或仅用作参数,此方法void Method(out TType)
void Method(TType)
输入TType
,因此它与协方差不兼容,因为规则(编译器规则基本上是为了类型安全)。
你可以通过实现另一个不包含该方法的接口来修复这个问题,你将从该接口失去对该方法的访问权限(你需要强制转换)。
interface IGenericInterfaceCovariant<out TType> where TType:IType
{
// don't use TType as input
void afunction(IType type); // `IType` is still valid though since its interface. notice the "I" and "T" differences before "Type"
}
interface IGenericInterface<TType> : IGenericInterfaceCovariant<TType> where TType:IType
{
void afunction(TType type);
}
那么你可以这样投。
return (IGenericInterfaceCovariant<IType>)instance;