2012-12-03 66 views
2

我在用XNA BoundingSpheres問題的參考。我想將BoundingSphere添加到BoundingSpheres列表中。目前,它是沿着以下幾條線:添加到列表C#結構

Aircraft(Vector3 pos, float radius, CollisionManager colMan) 
{ 
    BoundingSphere sphere = new BoundingSphere(pos, radius); 
    colMan.AddSphere(sphere) 
} 


List<BoundingSphere> spheres = new List<BoundingSphere>(); 

CollisionManager() 
{ 
    spheres = new List<BoundingSphere>(); 
} 

AddSphere(BoundingSphere boundingSphere) 
{ 
    spheres.Add(boundingSphere); 
} 

而不是添加引用,它似乎是添加的值。我相信這是因爲boundingSpheres是結構?我怎樣才能解決這個問題?我嘗試了ref關鍵字,但值仍然沒有在列表中更新。

+0

感謝您的回答。我想我會重新設計一下我的Collision Manager。應該只有數量有限的物體具有移動的碰撞盒,所以我希望能夠找到一種不會對性能造成太大影響的方式。 – Bushes

+0

考慮創建一個接口,我們稱它爲'ICollidable',它表示一個可碰撞的對象並將其邊界幾何體作爲一個屬性公開。然後,您可以創建一個可碰撞對象列表,這可能是您想要的,並相應地更新它們。請記住,如果替代方法是堆分配,那麼傳遞大型結構有時可能是有價值的,並且確保在跳到關於其性能的任何結論之前對代碼進行概要分析。 –

+0

@ColeCampbell實際上是我最初的想法。儘管我有同樣的問題。我在名爲CheckCollision(BoundingSphere sphere)的界面中創建了一個檢查衝突方法。碰撞管理器然後會調用這個方法並從列表中傳遞一個球體。通過的球體將是一個副本,但不參考原始的邊界球。我無法真正看到解決這個問題的好方法,它不涉及高耦合。 – Bushes

回答

0

值類型是按值傳遞(這意味着你要在方法或容器中的全新副本),以避免這種情況,你可以你的結構改變類,增加一個接口結構聲明和框的結構代替存儲對接口的引用。

但似乎你正在使用可變的結構,這是一個非常危險的,因爲你可以面對真正的危險行爲(見mutable structs considered harmful有詳細介紹)。

+0

'可變的結構被認爲是有害的,'就像'堆棧是一個實現細節'一樣,是當你處理像遊戲開發這樣的高性能場景時那種窗外事物。避免收集壓力可能非常重要,尤其是在移動/控制檯平臺上,這意味着可變結構可以很好地解決真正的問題。爲了這個目的,.NET Framework本身使用可變結構:查看通用List類的枚舉器的實現。 –

0

您必須將BoundingSphere的定義從class更改爲struct。這是不可能的,因爲它在an assembly outside of your control中定義。

你不能框結構,每次拆箱它的時候,你會得到你持有結構的副本。

也就是說,你可以做到這一點的唯一方法(在我看來,這不是一個好主意)是通過爲結構創建一個類包裝器,並將所有調用從屬性委託給結構內部:

public class BoundingSphereWrapper 
{ 
    // Set through constructor. 
    private readonly BoundingSphere _boundingSphere = ...; 

    // One of the forwarded calls. 
    public ContainmentType Contains(BoundingBox box) 
    { 
     // Forward the call. 
     return _boundingSphere.Contains(box); 
    } 

    // And so on... 
} 

當然,你不能將這些類的實例傳遞給期待BoundingSphere成員,你必須嘗試和發現變化(這是幾乎是不可能的,除非該實例是通過引用傳遞)當你公開底層結構時。

也就是說,雖然,你真的不希望這樣做;該結構的設計人員可能選擇它作爲一個結構的原因如下:

  • 雖然可變(這是一個沒有任何與結構處理時),則壽命旨在限於
  • 有可能是其中很多都是同時實例化的,在堆棧上執行此操作比在堆上執行操作效率更高(這會導致大量第一代垃圾回收,這對於遊戲平臺的性能肯定會有影響)
2

待straightforawrd,你不能,至少沒有直接。結構是value types,因此按價值傳遞和存儲。即使明智地使用ref關鍵字也不會繞過它,因爲List<T>.Item無法返回對值類型的引用。

的變通辦法是要麼把你structclass,或嵌入stuct一個class裏面,或者,只是對付它的值類型的事實並進行適當處理(即,不要試圖修改本地副本,但在更改時替換列表中的值)。最後一個選項是,imo,最好的。