对2D数组中的每个元素执行操作

时间:2015-01-07 03:32:42

标签: c# lambda

我目前正在开发一款游戏,其中背景由二维瓷砖阵列表示。 Tile是一个相对简单的类,包含图形和可遍历信息。在我的代码中,我发现自己想要经常做类似于以下的事情:

for (int x = 0; x < TileMap.GetLength(0); x++)
{
    for (int y = 0; y < TileMap.GetLength(1); y++)
    {
        // do something
    }
}

显然有更好的方法,对吧?我想也许我可以创建一个扩展方法,它接受一个Action参数迭代数组并为每个Tile执行指定的操作,如下所示:

public static void PerformAction(this Tile[,] tileMap, Action<Tile> action)
{
    for (int x = 0; x < tileMap.GetLength(0); x++)
    {
        for (int y = 0; y < tileMap.GetLength(1); y++)
        {
            action(tileMap[x, y]);
        }
    }
}

然后像这样使用它(只是一个例子):

TileMap.PerformAction(t => t = new Tile());

但这不起作用。我可以在扩展方法或lambda表达式中设置断点,并观察每次迭代都会遇到断点,但TileMap中的实际Tile保持不变。对于上面的示例,如果之前为null,则所有Tiles仍为null。难道我做错了什么?有没有更好的方法来做我想做的事情?

1 个答案:

答案 0 :(得分:3)

根据你的描述,听起来你希望能够修改数组本身的元素,而不仅仅是它引用的对象(或它存储的值......不清楚Tile是否为{{1}或者class)。当然,调用struct委托,只是将数组中的值传递给方法,而不是对数组元素的引用。在该场景中,委托无法修改数组本身。

解决此问题的一种方法是通过引用而不是默认的by-value传递数组元素。内置委托类型不支持by-reference参数传递。但您可以声明自己的委托(有关详细信息,请参阅this answer):

Action<T>

然后您可以像这样实现扩展方法:

delegate void ActionRef<T>(ref T t);

从这样的方法传递委托:

public static void PerformAction(this Tile[,] tileMap, ActionRef<Tile> action)
{
    for (int x = 0; x < tileMap.GetLength(0); x++)
    {
        for (int y = 0; y < tileMap.GetLength(1); y++)
        {
            action(ref tileMap[x, y]);
        }
    }
}

另一种方法(和恕我直言,可能有点清洁)是让行动代表在需要时返回一个新值:

void MyActionMethod(ref Tile tile)
{
    // do something to tile
}

然后你的方法看起来像这样:

public static void PerformAction(this Tile[,] tileMap, Func<Tile, Tile> action)
{
    for (int x = 0; x < tileMap.GetLength(0); x++)
    {
        for (int y = 0; y < tileMap.GetLength(1); y++)
        {
            tileMap[x, y] = action(tileMap[x, y]);
        }
    }
}