C# T必须是反变有效的
这有什么问题C# T必须是反变有效的,c#,.net,generics,covariance,contravariance,C#,.net,Generics,Covariance,Contravariance,这有什么问题 interface IRepository<out T> where T : IBusinessEntity { IQueryable<T> GetAll(); void Save(T t); void Delete(T t); } 接口i假设,其中T:IBusinessEntity { IQueryable GetAll(); 无效保存(T); 无效删除(T); } 它说: 无效差异:类型参数“T”在“MyNamespace.I
interface IRepository<out T> where T : IBusinessEntity
{
IQueryable<T> GetAll();
void Save(T t);
void Delete(T t);
}
接口i假设,其中T:IBusinessEntity
{
IQueryable GetAll();
无效保存(T);
无效删除(T);
}
它说:
无效差异:类型参数“T”在“MyNamespace.IRepository.Delete(T)”上必须相反有效T’是协变的。以下两种方法是错误的:
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);
}
接口i假设,其中T:IBusinessEntity
{
无效保存(T);
无效删除(T);
}
您只能协变地使用out
类型参数,即在返回类型中。因此,IQueryable GetAll()
是正确的,但是void Delete(T)
不是
由于T
在您的类中同时使用并列和倒数形式,因此此处不能使用out
(也不能使用in
)
如果你想更多地了解这背后的理论背景,请稍作休息,阅读下面的文章
欢迎回来。那么,如果您需要存储库中的所有这些方法,但仍然需要一个协变接口,您会怎么做?您可以将协变部分提取到其自己的接口中:
interface IDataSource<out T> where T : IBusinessEntity
{
IQueryable<T> GetAll();
}
interface IRepository<T> : IDataSource<T> where T : IBusinessEntity
{
void Save(T t);
void Delete(T t);
}
接口IDataSource,其中T:IBusinessEntity
{
IQueryable GetAll();
}
接口IRepository:IDataSource其中T:IBusinessEntity
{
无效保存(T);
无效删除(T);
}
这也是.NET BCL解决此问题的方法:
IEnumerable
是协变的,但只支持“读取操作”ICollection
是IEnumerable
的一个子类型,允许读写操作,因此本身不能是协变的。考虑一下如果编译器允许:
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
接口IR
{
无效D(T);
}
C类:红外
{
公共空间D(哺乳动物m)
{
m、 长发();
}
}
...
IR x=新的C();
//合法,因为动物是协变的,哺乳动物可以转换为动物
x、 D(新鱼());//因为IR.D带走一只动物是合法的
你只是想在鱼身上长头发
“out”表示“T仅用于输出位置”。您在输入位置使用它。请注意,它可以在参数中,但只能使用类似于
操作的操作来再次反转方向。完整且清晰的回答。谢谢,现在我终于明白为什么关键字是in
和out
。类的输入和类的输出。这已经是一段时间的斗争了,谢谢。你最后做了什么?我也面临同样的问题。答案并不能真正解决问题;我需要在同一类中获取、保存和删除。对不起,我不记得了。那是4年前的事了。我永远无法理解为什么在解释某事时,T
和IR
和C
和x
是有效的变量名。这也适用于MSDN文档,尤其是泛型文档。什么是“D”?@David:它们是有效的,因为它们符合C#规范中的标识符标准,但我认为你的意思是在教学上有效。使用短名称的教学法是要巧妙地提醒读者,这是一个普遍的、广泛适用的例子,他们应该抽象地思考,而不是解决特定领域中的特定问题。从教学学上讲,这不是有效的。。。当例子把概念带到脑海中,而符号带来的意义远远不是概念化。但这远远不是方差。我希望我在第一次尝试学习协方差/逆变时看到这个解释:“out”表示“T”仅用于输出位置。您正在输入位置使用它。”我刚才假设in
和out
是任意重用的关键字。@AndrewKeeton:我们经历了一个漫长的设计过程,考虑了许多选项。与所有设计过程一样,有许多相互竞争的因素必须相互权衡。请参阅我2007年关于该主题的文章,了解一些选项及其优缺点: