我需要使用嵌套的for / foreach循环更改列表中的项目。 问题是我无法使用带或不带点符号的LINQ。 传统的方式是这样的:
foreach (MapObjectLayer mapObjectLayer in map.Objects)
{
foreach (MapObject mapObject in mapObjectLayer.MapObjects)
{
for (int i = 0; i < mapObject.Points.Count; i++)
{
mapObject.Points[i] = new Vector2(
mapObject.Points[i].X * map.Scale,
mapObject.Points[i].Y * map.Scale);
}
}
}
使用LINQ,失败了:
var test = (from mol in map.Objects
from mo in mol.MapObjects
from p in mo.Points
select p).ToList();
for (int i = 0; i < test.Count(); i++)
{
test[i] = new Vector2(
test[i].X * map.Scale,
test[i].Y * map.Scale);
}
这失败了:
map.Objects.ForEach(l => l.MapObjects.ForEach(t => t.Points.ForEach(p => p = p * map.Scale)));
如果我能让点符号变体工作,我会非常高兴,但我不知道它为什么会失败。 使用调试器很明显,通过检查Points列表,矢量没有使用两个LINQ变量相乘。
更新:Vector2是一个结构
更新:我找到了另外两个单行(工作单位):
map.Objects.SelectMany(m => m.MapObjects).ToList().ForEach(o => o.Points = o.Points.Select(p => p * 2).ToList());
map.Objects.ForEach(l => l.MapObjects.ForEach(t => t.Points = t.Points.Select(p => p * 2).ToList()));
答案 0 :(得分:2)
常规foreach
是最好的方法。 LINQ专为查询而设计。你可以在一行中完成它,但它不会优雅或可读。方法如下:
map.Objects.ForEach(l => l.MapObjects.ForEach(t => Enumerable.Range(0, t.Points.Count).ToList().ForEach(i => t.Points[i] *= map.Scale)));
您的版本无效的原因是Vector2
是值类型。在查询中,它的值被复制,因此当您执行p => p = ...
时,您将分配给变量的副本。
使用原始代码。 LINQ不能代替循环。
答案 1 :(得分:1)
您也可以使用Linq收集项目(实际上Resharper将提供从嵌套foreach到linq的重构),但您必须注意收集的内容和更新内容。
初始linq查询语法示例将Points的副本收集到新List中,然后使用Vector2的新实例替换此新列表的每个元素。即使Vector2是一个引用类型,只有新列表会改变而不是原始的map.Objects-substructure。
如果
,它会以你想要的方式工作您将分配替代Vector2项的属性:
test [i] .X * = map.Scale