Jonesopolis
Jonesopolis

Reputation: 25370

Returning IEnumerable Implementation from within Task

I can do:

public static IEnumerable<string> Do()
{
   return new List<string>();
}

But if I'm returning a Task, I'm not allowed to do the same thing:

public static Task<IEnumerable<string>> DoTask()
{
    return Task.Factory.StartNew(() =>
    {
        return new List<string>(); //no no
    });
}

I'm implementing a async repository in .NET 4.0 and ran across this. I was just curious why the compiler can't cast my List down when wrapped in a Task? Of course, my work around is just throwing AsEnumerable on it , but I wonder why this limitation exists?

Upvotes: 0

Views: 2136

Answers (1)

Alexei Levenkov
Alexei Levenkov

Reputation: 100527

Converting from Task<List<string>> to Task<IEnumerable<string>> require Task<T> to be covariant AND inner types to be interfaces. Neither is true in this case, so conversion not allowed.

Obvious fix - to cast result of Task to necessary type either by explicitly specifying type for lambda

return Task.Factory.StartNew((Func<IEnumerable<string>>)
  (() =>
  {
    return new List<string>(); 
  }));

or implicitly by casting result:

  return (IEnumerable<string>)new List<string>();

Detailed information - Covariance and Contravariance FAQ


Why Task<List<string>> is result of TaskFactory.StartNew call:

Lambda passed to the StartNew call does not explicitly specify its type so compiler infers its return type from return statement. Since return clearly states new List... overall type of lambda is equivalent in this case to Func<List<string>>.

Upvotes: 4

Related Questions