0

我需要使用嵌套的 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)));

如果我能让点符号变体工作,我会很高兴,但我不知道它为什么会失败。使用调试器,通过检查点列表很明显,向量没有使用两个 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()));
4

2 回答 2

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)));

The reason that your version didn't work is because Vector2 is a value type. In the query, it's value is copied, so when you do p => p = ... you are assigning to a copy of the variable.

Use the original code. LINQ is not a replacement for loops.

于 2012-05-19T17:19:49.790 回答
1

You can use Linq as well to collect items (in fact Resharper will offer a refactoring from nested foreach to linq), but you have to take care what you collect and what you update.

The initial linq query syntax example collects copies of Points into a new List and then replaces each element of this new list with a new instance of Vector2. Even if Vector2 would have been a referency type only the new list would change rather than the original map.Objects-substructure.

It would work the way you want it if

  • you work with reference rather than value types and
  • you'd assign the properties of the instead-of-Vector2 items:

    test[i].X *= map.Scale

于 2012-05-31T14:12:58.180 回答