这与协方差和逆变有关。
在您的问题中,您提到了以下内容:
... GenericQueryRepository 实现 IGenericQueryRepository 和 Client 实现 IClient。
让我们通过使用 fruits 来简化:Fruit 实现了 IFruit。我们还将创建一个 Tree 类。
public interface IFruit { }
public class Fruit : IFruit { }
public class Tree<T> where T : IFruit { }
Tree<IFruit> tree = new Tree<Fruit>() // error
这将重现您遇到的相同类型的错误。为什么?简单的。
虽然 Fruit 实现了 IFruit,但 Fruit Tree 并没有实现 IFruit Tree。Fruit Tree 和 IFruit Tree 之间没有演员表,尽管你会预料到。它们都是树,但具有不同的类型参数。它们的类型参数彼此相关的事实并不重要。
换句话说:Fruit Tree 和 IFruit Tree 之间不可能进行强制转换,因为它们的类型参数不匹配。
通常,在使用泛型进行强制转换时,请确保它们的类型参数匹配。但是,也有一些例外情况。请参阅泛型接口中的差异。
在您的情况下,您可以通过使用 IClient 作为 GenericQueryRepository 类的类型参数来修复它。这样做将允许强制转换,因为类型参数匹配。但我不知道您的应用程序架构,因此此修复可能不适用于您的情况。
编辑:为了更容易理解,复制粘贴下面的代码,看看编译器是怎么说的。
interface IFruit { }
class Fruit : IFruit { }
interface ITree<T> where T : IFruit { }
class Tree<T> : ITree<T> where T : IFruit { }
class Program
{
static void Main(string[] args)
{
ITree<Fruit> test1 = new Tree<Fruit>(); // compiles: type parameters match
ITree<IFruit> test2 = new Tree<Fruit>(); // fails: type parameters don't match
ITree<Fruit> test3 = new Tree<IFruit>(); // fails: type parameters don't match
ITree<IFruit> test4 = new Tree<IFruit>(); // compiles: type parameters match
IEnumerable<IFruit> test5 = new List<Fruit>(); // compiles: this is one of the exceptional cases
}
}
这应该弄清楚什么是可能的,什么是不可能的。