1

So I understand that the await keyword will start a Task, suspend execution, and then later resume execution and return the Task's result at some point in the future after the Task has completed.

In the code below, I am mapping a list of user IDs to a list of email addresses using Select(). The mapping function supplied to Select() will create and await a Task that returns an email address. So execution will be suspended inside the mapping function and then later resumed, where the await keyword will return the email address from the Task, which is then returned by the mapping function.

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;

public class Program
{
    static void Main()
    {
        List<int> userIds = new List<int>{54, 24, 67};

        List<string> userEmails = userIds.Select
        (
            async userId => await GetUserEmailAsync(userId)
        );

        Console.WriteLine("Emails: " + String.Join(", ", userEmails.ToArray()));
    }

    private static Task<string> GetUserEmailAsync(int userId)
    {
        return new Task<string>(() => "user" + userId + "@gmail.com");
    }
}

However, I get an error describing that the Select() call is returning a list of Tasks instead of strings (the email addresses). But since the mapping function contains the await and returns a string, shouldn't the Select() call return a list of strings?

  • 3
    There is an explanation here https://stackoverflow.com/a/23113336/698589 – dlxeon May 04 '18 at 21:42
  • 2
    Note that first sentence is not correct - await will not start a task. So if you await unstarted task, like in given code - it will just wait forever (or until you start it). – Evk May 04 '18 at 21:48
  • Oh, so the task is started within the constructor like with Promises in JavaScript? –  May 04 '18 at 21:50
  • 1
    It's started with Start method, but you almost never need to do it, nor do you ever need to create task with constructor. Instead, you usually use Task.Run and similar constructs, which all return already started task. Result of async method is also always started task. – Evk May 04 '18 at 21:53

1 Answers1

-1

Thats because async methods always returns Task or Task<T>. So if you have async userId => await GetUserEmailAsinc(userId). It in fact means this:

static async Task<string> MyFunction(string userId) {
    return await GetUserEmailAsync(userId);
}

In current version (7.*) of C#, there is no async/await syntax sugar for enumerables/collections. Its planned for next version, bat as fair as I know, there is still just a concept.

TcKs
  • 25,849
  • 11
  • 66
  • 104