Enumerable.SelectMany 引发错误 CS0411 - 无法从使用情况推断

Enumerable.SelectMany throws Error CS0411 - cannot be inferred from the usage

提问人:Amir M 提问时间:11/9/2023 最后编辑:Amir M 更新时间:11/9/2023 访问量:62

问:

我正在使用 c#、.net 6.0

我正在尝试将 IEnumerable 方法和 ot 的调用方方法转换为异步工作。

我有一个看起来像这样的代码:

    public IEnumerable<MyUser> getUsers()
{
    return AccountById
        .Keys
        .SelectMany(accountId => {
            try
            {
                return getUsersFor(accountId)
                    .Select(x => new MyUser(x,
                        SetAccountUniqueName(AccountById[accountId].Name,
                            AccountById[accountId].Id)));
            }
            catch (Exception ex)
            {
                _log.Error(ex);
                return Enumerable.Empty<MyUser>();
            }
        });
}

public IEnumerable<User> getUsersFor(string accountId)
{
    ListUsersResponse usersResponse;
    string marker = null;
    do
    {
        using (var myClient = new ServiceClient(accountId))
        {
            usersResponse =
                myClient.ListUsersAsync(
                        new ListUsersRequest { Marker = marker, MaxItems = MAX_ITEMS })
                    .Result;
            foreach (var user in usersResponse.Users)
            {
                yield return user;
            }
        }

        marker = usersResponse.Marker;
    } while (usersResponse.IsTruncated);
}

我将 getUsers() 和 getUsersFor() 转换为异步工作。

我尝试了这段代码:

    public async Task<List<MyUser>> GetUsersAsync()
    {
        return await AccountById
            .Keys
            .SelectMany(async accountId =>
            {
                try
                {
                    await foreach (var user in GetUsersForAsync(accountId))
                    {
                        var u = new MyUser(user,
                            SetAccountUniqueName(AccountById[accountId].Name,
                                AccountById[accountId].Id));
                        return u;
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, $"Failed to get account {accountId} users list.");
                    return Enumerable.Empty<MyUser>();
                }
            });
    }

    public async IAsyncEnumerable<User> GetUsersForAsync(string accountId)
    {
        ListUsersResponse usersResponse;
        string marker = null;
        do
        {
            using (var myClient = new ServiceClient(accountId))
            {
                usersResponse =
                    await myClient.ListUsersAsync(
                            new ListUsersRequest { Marker = marker, MaxItems = MAX_ITEMS });
                foreach (var user in usersResponse.Users)
                {
                    yield return user;
                }
            }

            marker = usersResponse.Marker;
        } while (usersResponse.IsTruncated);
    }

但是我收到此错误:

无法从用法中推断出方法“Enumerable.SelectMany<TSource, TResult>(IEnumerable, Func<TSource, IEnumerable>)”的类型参数。尝试显式指定类型参数。

C# LINQ async-await IEnumerable yield

评论

0赞 Jeroen van Langen 11/9/2023
“无法从使用情况推断”表示编译器无法确定您返回的类型。您应该尝试定义它:?.SelectMany<User>(...
0赞 MakePeaceGreatAgain 11/9/2023
什么是退货?AccountById
0赞 Amir M 11/9/2023
@MakePeaceGreatAgain是AccountByIdConcurrentDictionary<string, Account>
1赞 Klaus Gütter 11/9/2023
try 块中的代码返回 a ,而 catch 块中的代码会重新调整 .MyUserIEnumerable<MyUser>

答:

0赞 Svyatoslav Danyliv 11/9/2023 #1

不应将 LINQ 用于异步操作。选择许多异步调用返回,如果您不等待它们,则这是错误的方式。Task

简单会适用于您的情况,不要让事情复杂化。foreach

public async Task<List<MyUser>> GetUsersAsync()
{
    var result = new List<MyUser>();
    foreach (var accountId in AccountById.Keys)
    {
        try
        {
            await foreach (var user in GetUsersForAsync(accountId))
            {
                var u = new MyUser(user,
                    SetAccountUniqueName(AccountById[accountId].Name,
                        AccountById[accountId].Id));
                result.Add(u);
            }
        }
        catch (Exception ex)
        {
            _logger.Error(ex, $"Failed to get account {accountId} users list.");
        }    
    }

    return result;
}