我目前正在开发一款游戏,其中背景由二维瓷砖阵列表示。 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。难道我做错了什么?有没有更好的方法来做我想做的事情?
答案 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]);
}
}
}