繁体   English   中英

C#、lambda:如何处理冗余调用?

[英]C#, lambda : How are redundant calls handled?

我很好奇编译器如何处理以下表达式:

    var collapsed = elements.GroupBy(elm => elm.OrderIdentifier).Select(group => new ModelsBase.Laser.Element()
    {
        CuttingDurationInSeconds = group.Sum(itm => itm.CuttingDurationInSeconds),
        FladderDurationInSeconds = group.Sum(itm => itm.FladderDurationInSeconds),
        DeliveryDate = group.Min(itm => itm.DeliveryDate),
        EfterFladderOpstilTid = group.First().EfterFladderOpstilTid,
        EfterRadanOpstilTid = group.First().EfterRadanOpstilTid,
    });

如您所见,我使用了两次组总和,所以有人知道“组”列表是否会被迭代两次以获得两个总和,还是会对其进行优化,因此实际上只有 1 次完整的列表迭代。

LINQ 通常不是实现高性能的最佳方式,您获得的是编程的生产力,无需太多代码即可获得结果。

优化的可能性是有限的。 在查询到 SQL 的情况下,有一个经验法则:一个查询优于两个查询。

1)到SQL_Server只有一次往返

2) SQL Server 是用来优化这些查询的,如果服务器知道你下一步要做什么,优化就会越来越好。 优化是针对每个查询进行的,而不是针对多个查询进行的。

在 Linq to Objects 的情况下,构建大量查询绝对没有任何好处。 正如您的示例所示,它可能会导致多次迭代。 你让你的代码更简单、更容易阅读——但你放弃了控制,因此放弃了性能。

编译器当然不会优化其中的任何一个。

如果这是使用 LINQ to Objects,因此是委托,则委托将针对 5 个属性对每个组迭代 5 次。

如果这是使用 LINQ to SQL、实体框架或类似的东西,因此使用表达式树,那么基本上由查询提供程序来适当地优化它。

您可以通过在分组键中添加两个字段来优化您的请求

var collapsed = elements.GroupBy(elm => new{
   OrderIdentifier=elm.OrderIdentifier,
   EfterFladderOpstilTid=elm.EfterFladderOpstilTid,
   EfterRadanOpstilTid=elm.EfterRadanOpstilTid
})
   .Select(group => new ModelsBase.Laser.Element()
        {
            CuttingDurationInSeconds = group.Sum(itm => itm.CuttingDurationInSeconds),
            FladderDurationInSeconds = group.Sum(itm => itm.FladderDurationInSeconds),
            DeliveryDate = group.Min(itm => itm.DeliveryDate),
            EfterFladderOpstilTid = group.Key.EfterFladderOpstilTid,
            EfterRadanOpstilTid   = group.Key.EfterRadanOpstilTid,
        });

或者通过使用 LET 语句

var collapsed = from groupedElement in 
                        (from element in elements
                         group  element by element.OrderIdentifier into g
                        select g)
                        let First = groupedElement.First()
                        select  new ModelsBase.Laser.Element()
                        {
                            CuttingDurationInSeconds = groupedElement.Sum(itm => itm.CuttingDurationInSeconds),
                            FladderDurationInSeconds = groupedElement.Sum(itm => itm.FladderDurationInSeconds),
                            DeliveryDate = groupedElement.Min(itm => itm.DeliveryDate),
                            EfterFladderOpstilTid = First.EfterFladderOpstilTid,
                            EfterRadanOpstilTid = First.EfterRadanOpstilTid
                        };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM