T 必须逆变有效
这有什么问题吗?
interface IRepository<out T> where T : IBusinessEntity
{
IQueryable<T> GetAll();
void Save(T t);
void Delete(T t);
}
它说:
无效方差:类型参数“T”必须是逆变有效的 在“MyNamespace.IRepository.Delete(T)”上。 “T”是协变的。
What is wrong with this?
interface IRepository<out T> where T : IBusinessEntity
{
IQueryable<T> GetAll();
void Save(T t);
void Delete(T t);
}
It says:
Invalid variance: The type parameter 'T' must be contravariantly valid
on 'MyNamespace.IRepository.Delete(T)'. 'T' is covariant.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
考虑一下如果编译器允许这样做会发生什么:
而您只是试图在鱼上长出毛发。
“out”表示“T 仅用于输出位置”。您正在输入位置使用它。
Consider what would happen if the compiler allowed that:
And you just tried to grow hair on a fish.
The "out" means "T is only used in output positions". You are using it in an input position.
您只能以协变方式(即在返回类型中)使用GetAll() 是正确的,但
out
类型参数。因此,IQueryablevoid Delete(T t)
不正确。由于
T
在您的类中同时使用协变和逆变,因此您不能在此处使用out
(也不能使用in
)。如果您想了解更多关于这背后的理论背景,请稍事休息并阅读“协方差”和逆变”维基百科文章。
欢迎回来。那么,如果您需要存储库中的所有这些方法但仍然需要协变接口,您该怎么办?您可以将协变部分提取到自己的接口中:
这也是 .NET BCL 解决此问题的方式:
IEnumerable
是协变的,但仅支持“读操作”。ICollection
是IEnumerable
的子类型,允许读取和写入操作,因此本身不能是协变的。You can use an
out
type parameter only covariantly, i.e., in the return type. Therefore,IQueryable<T> GetAll()
is correct, butvoid Delete(T t)
is not.Since
T
is used both co- and contravariantly in your class, you cannot useout
here (norin
).If you want to know more about the theoretical background behind this, take a quick break and read the "Covariance and Contravariance" Wikipedia article.
Welcome back. So, what do you do if you need all those methods in your repository but still need a covariant interface? You can extract the covariant part into its own interface:
This is also how the .NET BCL solves this issue:
IEnumerable<out T>
is covariant, but only supports "read operations".ICollection<T>
is a subtype ofIEnumerable<out T>
, allows read and write operations, and, thus, cannot be covariant itself.以下两种方法是错误的:
不能将
T
作为方法参数。仅当您希望它在泛型定义中是协变 (out T
) 时才作为返回类型。或者,如果您想要逆变,那么您可以仅使用泛型参数作为方法参数,而不使用返回类型:
The following two methods are wrong:
You can't have
T
as method argument. Only as return type if you want it to be covariant (out T
) in your generic definition.Or if you want contravariance then you could use the generic parameter only as method argument and not return type: