Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use async lambda expression with return bool in Enumerable.All extension

I have the following async method

private async Task<bool> HasPolicy(AuthorizationFilterContext context, string policy)
{
    var authorized = await _authorization.AuthorizeAsync(context.HttpContext.User, policy);
    return authorized.Succeeded;
}

I would like to use it in Enumerable.All and Enumerable.Any extension

var result1 = IsAndPolicy
    ? policys.All(async x => await HasPolicy(context, x))
    : policys.Any(async x => await HasPolicy(context, x));

But the above code gets the following error

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

like image 989
roroinpho21 Avatar asked Oct 24 '25 11:10

roroinpho21


2 Answers

One approach would be to project to an IEnumerable<Task<bool>>

var results = await Task.WhenAll(policys.Select(x => HasPolicy(context, x)));

var result1 = IsAndPolicy 
   ? results.All(x => x)                
   : results.Any(x => x);

The trouble with this approach, is you are processing all the items potentially needlessly.

like image 60
TheGeneral Avatar answered Oct 26 '25 03:10

TheGeneral


Michael Randall's answer produces the correct logical result but has to evaluate all policies, even though in both cases the evaluation can be short-circuited, by the first false result for All, or the first true result for Any.

This can be avoided by converting the tasks to an IAsyncenumerable<T> and using System.Linq.Async :

var resultTasks=policies.ToAsyncEnumerable()
                        .Select(async x => await HasPolicy(context, x));

var result1 = await (IsAndPolicy 
                       ? resultTasks.AllAsync(x => x)                
                       : resultTasks.AnyAsync(x => x));
like image 38
Panagiotis Kanavos Avatar answered Oct 26 '25 01:10

Panagiotis Kanavos