2011-02-18 77 views
31

这是什么问题?T必须是冲突有效

interface IRepository<out T> where T : IBusinessEntity 
{ 
    IQueryable<T> GetAll(); 
    void Save(T t); 
    void Delete(T t); 
} 

它说:

无效方差:类型参数 'T' 必须是 'MyNamespace.IRepository.Delete(T)' contravariantly有效。 'T'是协变的。

+1

你最终做了什么?我面临同样的问题。答案并不能真正解决问题。我需要GetAll,Save和Delete在同一类 – David 2015-08-07 08:51:05

+1

对不起,我不记得了。那是4年前。 – Eduardo 2015-08-07 19:35:24

回答

55

考虑会发生什么,如果编译器允许的是:

interface IR<out T> 
{ 
    void D(T t); 
} 

class C : IR<Mammal> 
{ 
    public void D(Mammal m) 
    { 
     m.GrowHair(); 
    } 
} 
... 
IR<Animal> x = new C(); 
// legal because T is covariant and Mammal is convertible to Animal 
x.D(new Fish()); // legal because IR<Animal>.D takes an Animal 

而你只是试图在一条鱼长出头发。

“out”表示“T仅用于输出位置”。您正在使用它在输入位置。

19

以下两种方法都是错误的:

void Save(T t); 
void Delete(T t); 

你不能有T作为方法参数。只有在您的泛型定义中希望它是协变(out T)时才作为返回类型。

或者,如果你想逆变那么你可以使用泛型参数只能作为方法的参数,而不是返回类型:

interface IRepository<in T> where T : IBusinessEntity 
{ 
    void Save(T t); 
    void Delete(T t); 
} 
+0

完整且干净的答案。谢谢 – 2012-01-28 17:42:19

37

您可以使用out型参数仅contravariantly,即在返回类型。因此,IQueryable<T> GetAll()是正确的,但void Delete(T t)不正确。

由于T在您的班级中同时使用,所以在这里不能使用out(或in)。

这里有一些背景:Covariance and Contravariance (Wikipedia)

+10

请注意,它*可以*在参数中,但只有像'Action `这样的东西可以再次反转方向。 – 2011-02-18 13:21:11

相关问题