我仍然与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;
我正在努力解决的重点;
非常感谢任何帮助。
答案 0 :(得分: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)
我更喜欢使用Rate = 1的新对象来合并ExchangeRate
对象。我认为这提供了更平滑,更清晰的代码。我强烈建议您将默认Rate设为1.0,然后您可以简单地与new ExchangeRate()
合并,而无需设置Rate属性。
要在新的ExchangeRate对象中设置Rate
的默认值,只需将初始化程序放在构造函数中
class ExchangeRate
{
public ExchangeRate()
{
this.Rate = 1.0;
}
// other stuff
}
答案 1 :(得分:0)
你需要这个吗?
var query = from cheque in ListOfCheques
let excRates = cheque.ExchangeRates ?? Enumerable.Empty()
let rate = excRates.Where(x => x.Type == Something).Select(x => x.Rate).FirstOrDefault() ?? 1
select cheque.NetAmount * rate;
var netTotal = query.Sum();
如果Rate是可以为null的,你可以通过使它可以为空而在let语句中熟练(例如Select(x => new int?(x.Rate))或删除?? 1并在你的select中熟练它。这将使:
var query = from cheque in ListOfCheques
let excRates = cheque.ExchangeRates ?? Enumerable.Empty()
let rate = excRates.Where(x => x.Type == Something).Select(x => x.Rate).FirstOrDefault()
select cheque.NetAmount * (rate != 0 ? rate : 1);
答案 2 :(得分:0)
这个怎么样?
var query =
from cheque in ListOfCheques
let rate =
cheque.ExchangeRates
.Where(exc => exc.Type == EnumExchangeRate.ForCheque)
.Select(exc => exc.Rate)
.DefaultIfEmpty(1.0M)
.First()
select rate * cheque.NetAmount;
var NetTotal = query.Sum();
您的问题中给出的LINQ查询示例包含您未解释的“额外”内容,因此我只包含了foreach
循环中的内容。