Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Covariance and contravariance on Tasks

Given the followin snippet, i quite dont understand WHY what im going to achieve is not possible:

Interface:

public interface IEntityRepository<out T> : IRepository<IEntity> {

    void RequeryDataBase();

    IEnumerable<T> Search(string pattern);

    Task<IEnumerable<T>> SearchAsync(string pattern);

    SearchContext Context { get; }

    string BaseTableName { get; }
  }

In IRepository<IEntity> are just simple generic CRUD defined.

I get an Error on this line: Task<IEnumerable<T>> SearchAsync(string pattern);

Error:

method return type must be output safe. invalid variance: the type parameter T must be invariantly valid on Task

Please help me understand, why i cant use <out T> with a Task<T>

like image 283
lokusking Avatar asked Jul 01 '16 07:07

lokusking


People also ask

What is the use of covariance and Contravariance?

Covariance and contravariance are terms that refer to the ability to use a more derived type (more specific) or a less derived type (less specific) than originally specified. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types.

What is the difference between covariance and Contravariance in delegates?

Covariance permits a method to have return type that is more derived than that defined in the delegate. Contravariance permits a method that has parameter types that are less derived than those in the delegate type.

Why is task not covariant?

The justification is that the advantage of covariance is outweighed by the disadvantage of clutter (i.e. everyone would have to make a decision about whether to use Task or ITask in every single place in their code).

Why is contravariance useful?

This is mainly useful when using already defined standard interfaces. Covariance means that you can use IEnumerable<string> in place where IEnumerable<object> is expected. Contravariance allows you to pass IComparable<object> as an argument of a method taking IComparable<string> .


1 Answers

Task<T> is not covariant. Variance can only be applied to generic interfaces (and delegates, but that's not relevant here).

e.g. Task<IEnumerable<Dog>> cannot be assigned to Task<IEnumerable<Animal>>. Because of this, your interface cannot be marked as covariant either.

You might want to see this related question.

like image 177
Charles Mager Avatar answered Sep 24 '22 01:09

Charles Mager