2009-05-19 33 views
0

以下方法非常简单,我试图通过将父项的另一个属性与父对象的查找进行匹配来确定行项目率。有几件事我不喜欢它,并且正在寻找优雅的解决方案,以使方法变得更小,更高效,或者两者兼而有之。它工作在当前状态,并不像它明显效率低下或任何事情。这不是任务关键或任何事情,更多的是好奇心。用linq清理一个简单的foreach

private decimal CalculateLaborTotal() 
    { 
     decimal result = 0; 

     foreach (ExtraWorkOrderLaborItem laborItem in Labor) 
     { 
      var rates = (from x in Project.ContractRates where x.ProjectRole.Name == laborItem.ProjectRole.Name select x).ToList(); 
      if (rates != null && rates.Count() > 0) 
      { 
       result += laborItem.Hours * rates[0].Rate; 
      } 
     } 
     return result; 
    } 

我喜欢用List<T>.ForEach()的想法,但我有一些麻烦,保持它足够简洁仍然容易阅读/维护。有什么想法吗?

+0

我们大概可以做一些猜测,但如果我们了解您正在使用的对象,以及为什么您要为每次计算引用“rates [0] .Rate”,那么帮助会容易得多。 – 2009-05-19 19:15:04

+0

var rates =(来自Project.ContractRates中的x,其中x.ProjectRole.Name == laborItem.ProjectRole.Name选择x.Rate).FirstOrDefault();可能会更好 – Keltex 2009-05-19 19:19:03

回答

4

像这样的东西应该这样做(未经测试!):

var result = 
    (from laborItem in Labor 
    let rate = (from x in Project.ContractRates 
       where x.ProjectRole.Name == laborItem.ProjectRole.Name 
       select x).FirstOrDefault() 
    where rate != null 
    select laborItem.Hours * rate.Rate).Sum(); 

或(假定只有一个速度能比得上)联接将会变得更加整洁:

var result = 
    (from laborItem in Labor 
    join rate in Project.ContractRates 
     on laborItem.ProjectRole.Name equals rate.ProjectRole.Name 
    select laborItem.Hours * rate.Rate).Sum(); 
0

略去rates != null检查 - linq查询可能是空的,但不是null。 如果您只需要列表的第一个元素,请使用List.FirstList.FirstOrDefault

使用没有优势。

2

好,嗯,这个怎么样:

// Lookup from name to IEnumerable<decimal>, assuming Rate is a decimal 
var ratesLookup = Project.ContractRates.ToLookup(x => x.ProjectRole.Name, 
               x => x.Rate); 

var query = (from laborItem in Labor 
      let rate = ratesGroup[laborItem].FirstOrDefault() 
      select laborItem.Hours * rate).Sum(); 

这里的好处是,你不需要通过合同利率的潜在大名单,每次看 - 你建立的查找一次。当然,这可能不是问题。