2015-01-07 55 views
1

我目前正在制作一个游戏,其中背景由二维数组的瓷砖表示。平铺是一个相对简单的类,它包含图形和可移动性信息。在我的代码,我多么希望自己做类似的东西往往如下:对二维数组中的每个元素执行操作

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

显然有更好的方式来做到这一点,对不对?我想,也许我可以创建需要的是迭代的操作参数,通过阵列,并执行指定的动作每个瓷砖,像这样的扩展方法:

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仍保持不变。对于上面的示例,如果之前为空,则所有Tiles仍然为空。难道我做错了什么?有没有更好的方式去做我想做的事情?

+0

你只是修改参数的值。如果您希望能够修改实际参考,则需要添加'ref'修饰符。 –

回答

3

从你的描述,这听起来像你希望能够修改元素的数组本身,而不是它所引用的对象(或者不重视它存储&hellip;现在还不清楚Tile是否是classstruct)。当然,调用Action<T>委托,您只是将数组中的值传递给方法,而不是对数组元素的引用。该代理无法在该方案中修改阵列本身。

解决此问题的一种方法是传递数组引用的元素,而不是默认的值。内置的委托类型不支持通过引用参数传递。但是你可以声明自己的代表(见this answer有详细介绍):

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

然后你的方法可能是这个样子:

Tile MyActionMethod(Tile tile) 
{ 
    // do something to tile 

    return tile; 
} 
相关问题