我仍然对LINQ表示满意,并且尝试将以下foreach循环重构为LINQ等效项。这是我要转换的foreach循环;
var NetTotal = 0M;
foreach (var cheque in ListOfCheques)
{
var exchangeRate = (from exc in cheque.ExchangeRates
where exc.Type == EnumExchangeRate.ForCheque
select exc).FirstOrDefault();
NetTotal = exchangeRate != null ? NetTotal + cheque.NetAmount * exchangeRate.Rate : NetTotal + cheque.NetAmount;
}
return NetTotal ;
以及我提出的LINQ代码;
var NetTotal = (from cheque in ListOfCheques
join exc in ListOfCheques.SelectMany(b => b.ExchangeRates) on cheque.ID equals exrate.Cheque.ID into chequeWithRate
where income.ExchangeRates.Select(x => x.Type).Equals(EnumExchangeRate.ForCheque)
from ur in chequeWithRate.DefaultIfEmpty()
select ur).Sum(x => x.Cheque.NetAmount * x.Rate);
return NetTotal;
我正在努力的重点;
Check类中的“ ExchangeRates”列表可能不存在,即不需要汇率。
如果没有找到汇率,则应默认为1。我该如何设置...我希望在DefaultIfEmpty(1)中进行设置。
任何帮助是极大的赞赏。
最佳答案
像任何重构一样,只需一点一点地切掉。首先,像这样使用foreach
而不是Sum()
。
return ListOfCheques.Sum(c =>
{
var exchangeRate = (from exc in c.ExchangeRates
where exc.Type == EnumExchangeRate.ForCheque
select exc).FirstOrDefault();
return c.NetAmount * (exchangeRate ?? new ExchangeRate(){ Rate = 1 }).Rate;
});
(如果ExchangeRate.Rate属性的默认值为1,那就太好了)
我将exchangeRate函数重写为一种简单的格式。确定要
FirstOrDefault
而不是SingleOrDefault
吗?var exchangeRate = c.ExchangeRates.
FirstOrDefault(ex => ex.Type == EnumExchangeRate.ForCheque);
然后可以将其交换为第一条语句,将最终结果保留在下面。
如果您希望成为一个班轮!
return ListOfCheques.Sum(c => c.NetAmount *
(c.ExchangeRates.FirstOrDefault(ex => ex.Type == EnumExchangeRate.ForCheque)
?? new ExchangeRate() { Rate = 1 }).Rate);
编辑
澄清??新的ExchangeRate()
与其执行
!= null ? (amount * rate) : (rate)
而不是我将ExchangeRate
对象与一个新的Rate = 1的此类对象合并,我认为这提供了一段更加流畅和整洁的代码。我强烈建议您将默认的Rate设置为1.0,然后只需将new ExchangeRate()
合并即可,而无需设置Rate属性。要在新的ExchangeRate对象中为
Rate
设置默认值,只需将初始化程序放在构造函数中class ExchangeRate
{
public ExchangeRate()
{
this.Rate = 1.0;
}
// other stuff
}