C# – Linq and Async Lambdas

asynchronousclambdalinq

The following code…

using System;
using System.Linq;
using System.Threading.Tasks;

namespace ConsoleAsync
{
    class Program
    {
        static void Main(string[] args)
        {
            MainAsync(args).Wait();
            Console.ReadLine();
        }

        static async Task MainAsync(string[] args)
        {
            int[] test = new[] { 1, 2, 3, 4, 5 };

            if (test.Any(async i => await TestIt(i)))
                Console.WriteLine("Contains numbers > 3");
            else
                Console.WriteLine("Contains numbers <= 3");
        }

        public static async Task<bool> TestIt(int i)
        {
            return await Task.FromResult(i > 3);
        }
    }
}

Gives you the following error:-

CS4010: Cannot convert async lambda expression to delegate type
'Func<int, bool>'. An async lambda expression may return void, Task or
Task<T>, none of which are convertible to 'Func<int, bool>'.

On the line

if (test.Any(async i => await Test.TestIt(i)))

How do you work with Async Lambdas and linq?

Best Answer

You can't out of the box with LINQ. But you can write a little extension method which can make this work:

public static class AsyncExtensions
{
    public static async Task<bool> AnyAsync<T>(
        this IEnumerable<T> source, Func<T, Task<bool>> func)
    {
        foreach (var element in source)
        {
            if (await func(element))
                return true;
        }
        return false;
    }
}

And consume it like this:

static async Task MainAsync(string[] args)
{
    int[] test = new[] { 1, 2, 3, 4, 5 };

    if (await test.AnyAsync(async i => await TestIt(i))
        Console.WriteLine("Contains numbers > 3");
    else
        Console.WriteLine("Contains numbers <= 3");
}

It does feel a little cumbersome to me, but it achieves your goal.

Related Topic