2013-03-16 184 views
1

我正在寫一個遊戲,將有一個類只是爲了我在世界上的碰撞。我想在它的構造函數中傳遞兩個列表,一個包含所有敵人,另一個包含玩家射擊的所有子彈。使用ref列表以及列表如何保持更新

這是在XNA完成的2D遊戲遊戲,我應該這樣說,但我覺得這裏發佈,因爲它有更多的關於C#ref關鍵字。如果在將List傳遞給構造函數時使用ref關鍵字。

現在,如果我開始搞亂List中的元素,刪除和添加元素,修改等,將因爲它們通過引用傳遞,所以我永遠不必重新傳遞列表到該類,如果列表本身包含在其他類中?

public Collsion_manager(ref List<Bullet> bullets_world, ref List<Enemy_class> enemies_world) 
{ 
} 
+2

嗯...一般來說,我避免參考。我認爲它是一種代碼味道。 //列表是一個引用類型,以開頭;所以我沒有看到附加的關鍵字會給你買什麼。 //另外 - http://whathaveyoutried.com //在問我們之前,難道你不能輕易地嘗試過嗎? – 2013-03-16 03:12:21

+2

@JimG。有一個原因使用引用類型的ref,語義是實際創建一個新的對象,你讓ref指向並改變給定列表的成員之間的差異。前者隻影響調用方法的本地引用,梯子會影響整個系統中指向該特定List對象的任何引用。奇怪的是,裁判對象可以成爲這樣的場景中的安全機制(儘管它不會阻止你做梯子)。 – 2013-03-16 03:16:32

+0

@Jimmy Hoffa:好的 - 但是沒有更簡單的方法來完成這些任務嗎? – 2013-03-16 03:19:19

回答

5

一般要避免ref傳遞一個引用類型(如List<T>)。您可以通過List<T> s並調用您想要的任何方法,並且更改將會通過罰款(如.Add().Remove(),.Sort()等)。您只需要傳入一次(在構造函數中)List<T>,即使您不使用ref,引用也將在對象的整個生命週期內保持有效。

它使不同的是,當你通過List<T>通過ref,要傳遞一個參考(指針)到可變參數,而不是對象。如果您想分配給變量一個新的List<T>,這隻會有所作爲。

我做了一個小程序,說明這種差異。

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<int> listA = new List<int> { 1, 2, 3 }; 
     List<int> listB = new List<int> { 1, 2, 3 }; 

     Update(listA); 
     UpdateRef(ref listB); 

     Console.WriteLine("listA"); 
     foreach (var val in listA) 
      Console.WriteLine(val); 

     Console.WriteLine("listB"); 
     foreach (var val in listB) 
      Console.WriteLine(val); 
    } 

    static void Update(List<int> list) 
    { 
     list = new List<int>() { 4, 5, 6 }; 
    } 

    static void UpdateRef(ref List<int> list) 
    { 
     list = new List<int>() { 4, 5, 6 }; 
    } 
} 

這裏是由程序產生的輸出:

listA 
1 
2 
3 
listB 
4 
5 
6 

注意如何listB包含新List<T>listA沒有。這是因爲我們參考了變量listB

+0

注意,ref和out的目的都是爲了多重回報。如果你有一個返回值,不要使用ref或out,只是返回它。更好的實踐與現代多回報。net是返回一個元組,並且永遠不會使用out或ref – 2013-03-16 12:57:53

+0

這對於引用類型無關緊要,但這是什麼問題。對於值類型是的,它可以使方法返回多個值。 – 2013-03-16 15:19:51

+0

值類型可以返回就好,沒有理由使用public void AddOne(ref int i)而不是public int AddOne(int i),用法是i = AddOne(i); ref和out僅存在多個返回值,ref是必需的,因爲您不能輸出值類型 – 2013-03-16 19:17:53