Edu*_*rdo 34 .net c# generics covariance contravariance
这有什么问题?
interface IRepository<out T> where T : IBusinessEntity
{
IQueryable<T> GetAll();
void Save(T t);
void Delete(T t);
}
Run Code Online (Sandbox Code Playgroud)
它说:
方差无效:类型参数"T"必须在"MyNamespace.IRepository.Delete(T)"上具有矛盾的有效性.'T'是协变的.
Eri*_*ert 60
考虑如果编译器允许的话会发生什么:
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
Run Code Online (Sandbox Code Playgroud)
你只是试着在鱼上长出头发.
"out"表示"T仅用于输出位置".您正在输入位置使用它.
Hei*_*nzi 42
您只能共同使用out
类型参数,即返回类型.因此,IQueryable<T> GetAll()
是正确的,但void Delete(T t)
不是.
既然T
在你的班级中同时使用和不相符,你就不能out
在这里使用(也不是in
).
如果您想进一步了解这背后的理论背景,请快速阅读并阅读"Covariance and Contravariance"维基百科文章.
欢迎回来.那么,如果您需要存储库中的所有这些方法但仍需要协变接口,您会怎么做?您可以将协变部分提取到其自己的界面中:
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);
}
Run Code Online (Sandbox Code Playgroud)
这也是.NET BCL如何解决这个问题:IEnumerable<out T>
是协变的,但只支持"读操作".ICollection<T>
是一个子类型IEnumerable<out T>
,允许读写操作,因此,本身不能协变.
Dar*_*rov 21
以下两种方法都是错误的:
void Save(T t);
void Delete(T t);
Run Code Online (Sandbox Code Playgroud)
你不能拥有T
方法参数.仅作为返回类型,如果您希望它out T
在通用定义中是covariant().
或者如果你想要逆变,那么你可以只使用泛型参数作为方法参数而不是返回类型:
interface IRepository<in T> where T : IBusinessEntity
{
void Save(T t);
void Delete(T t);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10596 次 |
最近记录: |