简体   繁体   English

这个LINQ查询太长了吗?

[英]Is this LINQ Query too long?

I'm new to LINQ, and don't want to over do it and make this code hard to maintain. 我是LINQ的新手,并且不想过度使用并且难以维护这些代码。

What do you think, is this LINQ Query too long? 你怎么看,这个LINQ查询太长了?

IList<ListViewItem> data = runAnalysis.PassAnalyses.Cast<PassAnalysis>().
  Select(passAnalysis => passAnalysis.GetValue(PeakStatistics.PeakStatisticsProperty)).
  SelectMany(peakStatistics => peakStatistics.Statistics.
    Where(statisticsBase => statisticsBase.Name == statisticType).
    Select(statisticsBase => new ListViewItem {Content = statisticsBase})).ToList();

I would say it's complicated due to nesting - but doesn't really need to be. 我会说它由于嵌套而变得复杂 - 但实际上并不需要。 Here's an example of a query which will give the same results (I think), but is simpler... 这是一个查询的例子,它会给出相同的结果(我认为),但更简单......

IList<ListViewItem> data = runAnalysis.PassAnalyses
      .Cast<PassAnalysis>()
      .Select(pass => pass.GetValue(PeakStatistics.PeakStatisticsProperty))
      .SelectMany(peakStats => peakStats.Statistics)
      .Where(statisticsBase => statisticsBase.Name == statisticType)
      .Select(statisticsBase => new ListViewItem {Content = statisticsBase})
      .ToList();

Without the nesting, it's easy to see how the transformation goes: 没有嵌套,很容易看出转换是如何进行的:

  • Start with PassAnalyses 从PassAnalyses开始
  • Cast each item to a PassAnalysis 将每个项目转换为PassAnalysis
  • Select the PeakStatistics 选择PeakStatistics
  • From each element, select all the Statistics within it, and flatten this sequence 从每个元素中选择其中的所有统计信息,并展平此序列
  • Filter any statistic with the wrong name 使用错误的名称过滤任何统计信息
  • Convert each result into a ListViewItem 将每个结果转换为ListViewItem
  • Convert the whole sequence into a list 将整个序列转换为列表

At this point, it's easy to convert it into a query expression: 此时,很容易将其转换为查询表达式:

IList<ListViewItem> data =
   (from PassAnalysis pass in runAnalysis.PassAnalyses
    from statsBase in pass.GetValue(PeakStatistics.PeakStatisticsProperty)
                          .Statistics
    where statsBase.Name == statisticType
    select new ListViewItem { Content = statsBase })
   .ToList();

Note that I've elided the first Select and the SelectMany; 请注意,我已经省略了第一个Select和SelectMany; you could use a let clause if you wanted. 你可以使用let子句。 Also I've used an explicit type for the pass range variable, to make the compiler generate the Cast<PassAnalysis >() call. 此外,我还为pass范围变量使用了显式类型,以使编译器生成Cast<PassAnalysis >()调用。

This is slightly different to the original version, as it will use a different form of SelectMany which propagates the original pass value too, but the results will be the same. 这与原始版本略有不同,因为它将使用不同形式的SelectMany传播原始pass值,但结果将是相同的。

Calling ToList() at the end is somewhat ugly as there's no query expression syntax for it... but you could use an intermediate variable for that: 最后调用ToList()有点难看,因为它没有查询表达式语法......但你可以使用一个中间变量:

var query = ...;
IList<ListViewItem> data = query.ToList();

IMO the query is fine, although it looks somewhat dense. IMO查询很好,虽然它看起来有些密集。 You could reformat it a bit to be more spacey: 您可以将其重新格式化以使其更加宽松:

var query = from analysis in runAnalysis.PassAnalyses.Cast<PassAnalysis>()
            let value = analysis.GetValue(PeakStatistics.PeakStatisticsProperty)
            from statistic in value.Statistics
            where statistic.Name == statisticType
            select new ListViewItem { Content = statistic };

IList<ListViewItem> data = query.ToList();

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

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