C # ใช้ async lambda expression พร้อม return bool ใน Enumerable นามสกุลทั้งหมด

Sep 28 2020

ฉันมีasyncวิธีการดังต่อไปนี้

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

ฉันต้องการใช้ในEnumerable.AllและEnumerable.Anyขยาย

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

แต่รหัสด้านบนได้รับข้อผิดพลาดต่อไปนี้

ข้อผิดพลาด CS4010 ไม่สามารถแปลงนิพจน์ async lambda เป็น delegate type 'Func <string, bool>' นิพจน์แลมบ์ดา async อาจคืนค่าเป็นโมฆะ Task หรือ Task ซึ่งไม่มีการแปลงค่าเป็น 'Func <string, bool>'

คำตอบ

4 00110001 Sep 28 2020 at 15:07

แนวทางหนึ่งคือการฉายภาพไปที่ไฟล์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);

ปัญหาเกี่ยวกับวิธีนี้คือคุณกำลังประมวลผลรายการทั้งหมดโดยไม่จำเป็น

2 PanagiotisKanavos Sep 28 2020 at 15:26

คำตอบไมเคิลแรนดอร์ผลิตผลตรรกะที่ถูกต้อง แต่จะต้องประเมินนโยบายทั้งหมดแม้ว่าในทั้งสองกรณีการประเมินผลที่สามารถลัดวงจรโดยคนแรกที่falseผลสำหรับAllหรือแรกผลสำหรับtrueAny

สิ่งนี้สามารถหลีกเลี่ยงได้โดยการแปลงงานเป็นIAsyncenumerable<T>และใช้System.LinqAsync :

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

var result1 = await (IsAndPolicy 
                       ? resultTasks.AllAsync(x => x)                
                       : resultTasks.AnyAsync(x => x));