2015-01-07 53 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; 
} 
相關問題