从专用类型转换为其通用接口

时间:2017-06-17 10:56:06

标签: c# generics

只要我们谈论动物和鱼类,通用类型协方差和反演法都很清楚,但为什么不应该这样做,你能解释一下吗?

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;

1 个答案:

答案 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;