You can use an out
type parameter only covariantly, i.e., in the return type. Therefore, IQueryable<T> GetAll()
is correct, but void Delete(T t)
is not.
Since T
is used both co- and contravariantly in your class, you cannot use out
here (nor in
).
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:
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);
}
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 of IEnumerable<out T>
, allows read and write operations, and, thus, cannot be covariant itself.