我目前有以下工作代码。然而,这是非常缓慢的。我知道将所有权作为查询而不是列表传递可能会简化并加快速度,但由于各种原因,这是不可能的。
如何在不创建新列表的情况下更新到位的馆藏列表?其他改进代码的建议?
internal List<DailyHoldingItem> TransformHoldingItemsToCurrency(List<DailyHoldingItem> holdings,string toCurrency)
{
//TODO - how to do this calculation in place, without creating a new list?
var query = (from holding in holdings
from fxRateHolding in amdw.FXRates
from fxRateToCur in amdw.FXRates
where
fxRateHolding.BaseCurrency == holding.Currency &&
fxRateToCur.BaseCurrency == toCurrency &&
fxRateHolding.ValueDate == holding.Date &&
fxRateToCur.ValueDate == holding.Date
select new { holding, fxRateHolding, fxRateToCur });
return query.Select(dhi =>
{
decimal factor = dhi.fxRateToCur.Value / dhi.fxRateHolding.Value;
dhi.holding.MarketValue *= factor;
dhi.holding.Fee *= factor;
dhi.holding.Remuneration *= factor;
return dhi.holding;
}).ToList();
}
答案 0 :(得分:6)
有一件事你可以使用联接加快速度,只评估有效的“目标”货币一次:
var targetRates = amdw.FXRates
.Where(rate => rate.BaseCurrency == toCurrency)
.ToList();
var query = from holding in holdings
join fxRateHolding in amdw.FXRates
on new { holding.Currency, holding.Date } equals
new { Currency = fxRateHolding.BaseCurrency,
Date = fxRateHolding.ValueDate }
join fxRateToCur in targetRates
on holding.Date equals fxRateToCur.ValueDate
select new { holding, fxRateHolding, fxRateToCur };
我个人不会尝试更新列表,而不会改变现有馆藏(正如您目前在Select
中所做的那样呼叫)。改变现有值往往会使您的代码难以推理 - 这就是为什么LINQ 设计以更实用的方式使用。
答案 1 :(得分:2)
更新对象时不应使用LINQ。 LINQ应该是无副作用的,你应该使用它来获取你想要改变的项目,然后对它们进行预测。
foreach(var dhi in query)
{
decimal factor = dhi.fxRateToCur.Value / dhi.fxRateHolding.Value;
dhi.holding.MarketValue *= factor;
dhi.holding.Fee *= factor;
dhi.holding.Remuneration *= factor;
}
您也可以使用List<T>
上定义的ForEach函数。
query.ToList().ForEach(dhi =>
{
decimal factor = dhi.fxRateToCur.Value / dhi.fxRateHolding.Value;
dhi.holding.MarketValue *= factor;
dhi.holding.Fee *= factor;
dhi.holding.Remuneration *= factor;
});
就像杰夫·梅尔卡多在评论中指出的那样,制作一个名单只是为了呼吁ForEach()
就不是一个好主意。
答案 2 :(得分:0)
嗯,你可以在SQL中做到这一点,请注意并非所有人都会期望在LINQ中产生副作用,但毕竟C#不是一种功能语言。
以下是您可以做的事情:
要更新单个属性,请执行以下操作:
from a in ab select a.prop = newVal;
要更新多个属性,您有以下选项:
在多个LINQ查询中拆分更新,每个查询更新一个属性(显然不是最好的主意)
执行以下from a in ab select new { x = a.prop = newVal, y = a.prop2 = newVal2 };
在LINQ方法链中(但不在查询表达式中),您可以执行ab.Select( a=>
{ x = a.prop = newVal; y = a.prop2 = newVal2; return x; };
(实际上在Linq to objects Update中,有人建议将这最后一种方法重构为扩展方法,这将允许它在查询表达式中使用,并澄清意图。