4

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>'.

2
  • Would you like to run these tasks concurrently or sequentially? Commented Sep 28, 2020 at 8:15
  • @TheodorZoulias, I think that in Any it should be sequentially and in All can be concurrently Commented Sep 28, 2020 at 8:20

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

5 Comments

@JohnathanBarclay thanks for the edit, this was done on my phone :P
@MichaelRandall No problem :)
@MichaelRandall, what about var result = IsAndPolicy ? policys.All((x) => HasPolicy(context, x).Result) : policys.Any((x) => HasPolicy(context, x).Result); ? I was hoping that this approach to be somehow written using async/await
@roroinpho21 although that would work... its very suspect, you are executing everything sequentially, not generating the IAsyncStateMachine from the async and await pattern, and is rather smelly. Panagiotis Kanavos really has the best approach here FWIW if you can call ToAsyncEnumerable
@roroinpho21 beware of the Task.Result property. It is OK to use it only for tasks that are known to be completed. Otherwise... problems.
3

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));

8 Comments

Fixed my name, upvoted as this is an awesome answer
Sorry (facepalm). I really need glasses
@PanagiotisKanavos it seems that resultTasks.AllAsync(x => x) (All doesn't exist) is not working, the parametter is incorect. Error CS0029 Cannot implicitly convert type 'System.Threading.Tasks.Task<bool>' to 'bool'
The System.Linq.Async library does not contain extension methods All and Any. At least not the version 4.1.1 that I have currently installed. It contains the AllAsync, AllAwaitAsync and AllAwaitWithCancellationAsync methods, and the same set for Any. In this case the XXXAwaitAsync variant is probably the most appropriate. You also need to provide async await lambdas, in order to convert from Task<bool> to ValueTask<bool>: resultTasks.AllAwaitAsync(async x => await x) etc.
@TheodorZoulias it's AllAsync and AnyAsync and there's no need to provide await in them. You're looking at the same Github sources I used. If you check the unit tests you'll see the operations don't need await. The problem was created by Select which returned IAsyncEnumerable<Task<bool>>
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.