这真的是异步的吗?IEnumerable< T>扩展

本文关键字:IEnumerable 扩展 真的 异步 | 更新日期: 2023-09-27 18:17:00

public static async Task<T> FirstIfNotNullOrEmptyAsync<T>(this Task<IEnumerable<T>> obj) where T : class
{
    var first = await Task.WhenAny(obj);
    return first?.Result?.FirstOrDefault() ?? null;
}
下面是显示完整 的另外两个方法

主方法(在这种情况下将只返回集合中的项或集合为空)

private async Task<IEnumerable<T>> fetchRecordsAsync(SqlCommand SqlCommand, bool isSingleRecord)
{..some code...}

下面是将获取集合并只传递T的调用者:

protected async Task<T> GetSingleRecord(SqlCommand SqlCommand)
{
    return await fetchRecordsAsync(SqlCommand, true).FirstIfNotNullOrEmptyAsync();
}

这是正确的方式与IEnumerable的异步扩展工作,或者它将做一个同步?

我真的需要创建另一个任务(首先)吗?

这真的是异步的吗?IEnumerable< T>扩展

这真的是异步吗?

是的。await Task.WhenAny将返回第一个完成的任务。在这样的任务(一个已完成的任务)上使用.Result不会导致同步等待。

顺便说一句,你不需要使用Task.WhenAny,你的方法可以简化如下:

public static async Task<T> FirstIfNotNullOrEmptyAsync<T>(
    this Task<IEnumerable<T>> obj) where T : class
{
    var result = await obj;
    return result?.FirstOrDefault();
}

它将异步地完成所有的工作,尽管那里有很多不必要的(尽管不是有害的,除了非常小的额外开销)。

当你只传递一个任务时,调用WhenAny是没有意义的。你不妨等待任务本身;它做同样的事情。

?? null没有意义。如果为"null",则设置为"null"。它已经是null了,所以你可以把它留下。

你也没有将一个空的Task传递给FirstIfNotNullOrEmptyAsync,你也不应该这样做。您也可能不应该为结果生成null IEnumerable。如果没有条目,你应该有一个空的序列。

也没有理由将该方法限制为仅适用于类序列。如果有人想使用值类型,没有真正的理由阻止他们。

调整方法的名称也是有意义的,这样它的名称就反映了它实际在做什么。

所以现在所有这些都可以归结为:

public static async Task<T> FirstOrDefaultAsync<T>(this Task<IEnumerable<T>> task)
{    
    return (await task).FirstOrDefault();
}

你的另一个方法也没有理由是async,因为你从来没有对等待的值做任何事情,除了在Task中重新包装它并返回它。只要返回Task,你有:

protected Task<T> GetSingleRecordAsync(SqlCommand SqlCommand)
{
    return fetchRecordsAsync(SqlCommand, true)
        .FirstOrDefaultAsync();
}