消除.net lambda表达式

本文关键字:表达式 lambda net 消除 | 更新日期: 2023-09-27 18:14:23

我正在评估我的c# . net web应用程序中的性能问题,并跟踪瓶颈到链式lambda表达式。我想完全删除lambda表达式,这样我就可以评估链中每个步骤的性能,但是我对lambda表达式相对较新。有没有人对如何将第二个lambda表达式重构成更传统的代码有任何想法,以便可以跟踪每个步骤或操作?

IEnumerable<OurPerformance> validPerformances = package.TimeFilteredValidPerformances(visitDateAndTime);
IEnumerable<WebPerformance> webPerformances = performanceGroup.RegularNonPassedPerformances
            .Where(performance => validPerformances.Select(perf => perf.PerformanceId).Contains(performance.PerformanceId))                
            .Select(performance =>
                new WebPerformance
                {
                    Date = performance.PerformanceDate.ToJavaScriptDateString(),
                    PerformanceId = performance.PerformanceId,
                    Title = performance.UserFriendlyTitle,
                    ProductionSeasonId = performance.ProductionSeasonId,
                    AvailableCount = performance.AvailableCount
                });
**IEnumerable<WebProduction> webProductions = webPerformances
            .GroupBy(performance => performance.ProductionSeasonId)
            .ToDictionary(grouping => SheddProduction.GetOurProduction(grouping.Key), grouping => grouping.ToList())
            .Select(perfsByProduction =>
                new WebProduction
                {
                    ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber,
                    Duration = perfsByProduction.Key.Duration,
                    Title = perfsByProduction.Key.UserFriendlyTitle,
                    Synopsis = perfsByProduction.Key.UserFriendlySynopsis,
                    ThumbnailImage = perfsByProduction.Key.PreviewImage,
                    Performances = perfsByProduction.Value
                });**

消除.net lambda表达式

我不能建议任何算法来排除lambda表达式,但我有另一个建议。尝试使用列表的webperformance代替IEnumerable集合。调用ToList()获取webperformance列表。在这种情况下,第二个lambda表达式将与list一起工作,而不会重新计算IEnumerable集合。

将其分解为更小的部分,更明显地转换为"传统"代码,实际上是相当直接的。只需将每个linq表达式结果存储在一个局部变量中,如下所示:

var groupedWebPerformances = webPerformances.GroupBy(performance => performance.ProductionSeasonId);
var webPerformancesDictionary = groupedWebPerformances .ToDictionary(grouping => SheddProduction.GetOurProduction(grouping.Key), grouping => grouping.ToList());
IEnumerable<WebProduction> webProductions = webPerformancesDictionary.Select(perfsByProduction =>
                new WebProduction
                {
                    ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber,
                    Duration = perfsByProduction.Key.Duration,
                    Title = perfsByProduction.Key.UserFriendlyTitle,
                    Synopsis = perfsByProduction.Key.UserFriendlySynopsis,
                    ThumbnailImage = perfsByProduction.Key.PreviewImage,
                    Performances = perfsByProduction.Value
                });

也就是说,你的性能问题是你到处都在使用IEnumerableIEnumerable可能会在每次使用时重新评估(取决于底层类型是什么),因此validPerformancesRegularNonPassedPerformances中的每个项目重新评估一次,webPerformances中的每个项目直到整个枚举被强制评估才得到评估,因此性能问题似乎是稍后出现的,但最有可能在这里:

validPerformances.Select(perf => perf.PerformanceId).Contains(performance.PerformanceId)

确保所有的枚举值在创建时执行ToList,从而强制一次求值:

List<OurPerformance> validPerformances = package.TimeFilteredValidPerformances(visitDateAndTime).ToList();
List<WebPerformance> webPerformances = performanceGroup.RegularNonPassedPerformances
            .Where(performance => validPerformances.Select(perf => perf.PerformanceId).Contains(performance.PerformanceId))                
            .Select(performance =>
                new WebPerformance
                {
                    Date = performance.PerformanceDate.ToJavaScriptDateString(),
                    PerformanceId = performance.PerformanceId,
                    Title = performance.UserFriendlyTitle,
                    ProductionSeasonId = performance.ProductionSeasonId,
                    AvailableCount = performance.AvailableCount
                })
             .ToList();
List<WebProduction> webProductions = webPerformances
            .GroupBy(performance => performance.ProductionSeasonId)
            .ToDictionary(grouping => SheddProduction.GetOurProduction(grouping.Key), grouping => grouping.ToList())
            .Select(perfsByProduction =>
                new WebProduction
                {
                    ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber,
                    Duration = perfsByProduction.Key.Duration,
                    Title = perfsByProduction.Key.UserFriendlyTitle,
                    Synopsis = perfsByProduction.Key.UserFriendlySynopsis,
                    ThumbnailImage = perfsByProduction.Key.PreviewImage,
                    Performances = perfsByProduction.Value
                })
            .ToList();

下面是将第二个lambda表达式重构为"传统"代码:

IEnumerable<IGrouping<string, WebProduction>> groupedPerformances 
    = webPerformances.GroupBy(performance => performance.ProductionSeasonId);
var dictionary = new Dictionary<string, List<WebProduction>>();
foreach (IGrouping<string, WebProduction> grouping in groupedPerformances)
{
    var group = new List<WebProduction>();
    foreach (WebProduction webProduction in grouping)
        group.Add(webProduction);
    dictionary.Add(grouping.Key, group);
}
var result = new List<WebProduction>();
foreach (KeyValuePair<string, List<WebProduction>> item in dictionary)
{
    var wp = new WebProduction
    {
        ProductionSeasonId = perfsByProduction.Key.ProductionSeasonNumber,
        Duration = perfsByProduction.Key.Duration,
        Title = perfsByProduction.Key.UserFriendlyTitle,
        Synopsis = perfsByProduction.Key.UserFriendlySynopsis,
        ThumbnailImage = perfsByProduction.Key.PreviewImage,
        Performances = perfsByProduction.Value
    };
    result.Add(wp);
}

我不知道你的SheddProduction.GetOurProduction方法的结果类型,因此我做了一些小的改变,但你可以得到要点…