只要我们谈论动物和鱼类,协方差和逆变就很清楚了,但是为什么这行不通,你能给我解释一下吗?
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;
在你的类型实现中没有协方差和逆变。 您应该将 out
用于协方差(这是您的情况(,或将 in
用于逆变。
interface IGenericInterface<out TType> where TType:IType // notice out keyword
{}
当你制作协方差TType
它应该只用作输出,例如仅在方法的返回类型中,如TType Method()
或仅作为 out 参数,此方法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;