【问题标题】:LINQ Select - CS0411 The type arguments cannot be inferred from the usage errorLINQ Select - CS0411 无法从使用错误中推断类型参数
【发布时间】:2021-02-01 23:55:39
【问题描述】:

我正在尝试将foreach 循环转换为Select 语句,如下所示:

ForEach 循环

List<Task> tasks = new List<Task>();
foreach (var proxyRequest in proxyRequests)
{
    tasks.Add(Task.Run(async () =>
    {
        try
        {
            Logger.LogInformation($"Request for the enrichment Giact [{message.SalesforceId}] \n {JsonSerializer.Serialize(proxyRequest)}");
            var result = await InquiryClient.CreateInquiry(proxyRequest, cancellationToken);

            Logger.LogInformation($"Response for the enrichment Giact [{message.SalesforceId}] \n {JsonSerializer.Serialize(result.Result)}");
            Response.GiactInquiryResponses.Add(result.Result);
         }
         catch (Exception ex)
         {
             Logger.LogError($"Error on requesting the enrichment Giact [{message.SalesforceId}] \n {ex}");
         }
     }));
}

选择语句:

proxyRequests.Select(x => tasks.Add(Task.Run(async () =>
{
    try
    {
        Logger.LogInformation($"Request for the enrichment Giact [{message.SalesforceId}] \n {JsonSerializer.Serialize(x)}");
        var result = await InquiryClient.CreateInquiry(x, cancellationToken);

        Logger.LogInformation($"Response for the enrichment Giact [{message.SalesforceId}] \n {JsonSerializer.Serialize(result.Result)}");
        Response.GiactInquiryResponses.Add(result.Result);
    }
    catch (Exception ex)
    {
        Logger.LogError($"Error on requesting the enrichment Giact [{message.SalesforceId}]\n {ex}");
    }
})));

但它给了我 CS0411 错误。我搜索了一下,发现Select 语句需要一个返回值,而foreach 循环更适合做这项工作。

是这样吗?使用Select 语句可以达到相同的结果吗?

【问题讨论】:

  • Select 不是foreach 的替代品,也不应该作为一个替代品使用。仅举一个例子,您的Select 语句代码不会运行任何Add 方法。

标签: c# linq async-await


【解决方案1】:

您可能需要将每个proxyRequest 投影到Task,然后使用ToList 运算符将延迟的IEnumerable&lt;Task&gt; 实现为任务列表:

List<Task> tasks = proxyRequests.Select(x => Task.Run(async () =>
{
    try
    {
        Logger.LogInformation($"Request for the enrichment Giact " 
            + $"[{message.SalesforceId}] \n {JsonSerializer.Serialize(x)}");
        var result = await InquiryClient.CreateInquiry(x, cancellationToken);

        Logger.LogInformation($"Response for the enrichment Giact "
            + $"[{message.SalesforceId}] \n {JsonSerializer.Serialize(result.Result)}");
        Response.GiactInquiryResponses.Add(result.Result);
    }
    catch (Exception ex)
    {
        Logger.LogError($"Error on requesting the enrichment Giact"
            + $" [{message.SalesforceId}]\n {ex}");
    }
})).ToList();

注意Response.GiactInquiryResponses.Add 方法可能被多个线程同时调用,因此,除非它是线程安全的,否则可能会导致未定义的行为(损坏的内部状态、随机异常等)。一般来说,最好避免在每个任务的主体内部产生副作用,而是自然地传播其结果:

List<Task<SomeType>> tasks = proxyRequests.Select(x => Task.Run(async () =>
{
    var result = await InquiryClient.CreateInquiry(x, cancellationToken);
    return result.Result;
})).ToList();

SomeType[] results = await Task.WhenAll(tasks);

【讨论】:

    【解决方案2】:

    Select 是一种投影方法,因此您在 select 中的操作应该返回一些内容。但是你的List.Addvoid

    试试下面的

    var tasks = proxyRequests.Select(x => Task.Run(()=>{/* your task code here */})).ToList();
    

    【讨论】:

      猜你喜欢
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多