2014-12-04 83 views
2

我不完全知道如何處理這種類型的問題。複製模板對象以從中創建一個新對象

private Dictionary<int, Tire> m_vehicleTireSelected = new Dictionary<int, Tire>() 
{ 
    {0, new TireCasual() 
    { 
     Name = "Monster Tire", 
     Position = new Vector3(-0.94f, -1.09f) 
    }}, 
    {1, new TireMonster() 
    { 
     Name = "Casual Tire", 
     Position = new Vector3(1.05f, -1.09f) 
    }} 
}; 


public void ChangeTire(int tireIndex, int tireKey) 
{ 
    m_bus.ChangeTire(tireIndex, m_vehicleTireSelected[tireKey]); 
} 

所以我想在這裏使用Dictionary來存儲一些輪胎模板對象,然後再用新的來更改它們。這裏的問題是,當我從字典中分配輪胎時,它仍然是同一輪胎,因爲它是一個引用類型變量,但最終我希望它是COPY。有人可以幫我解決問題,也許可以提出一個想法,我可以如何處理這種情況?我還應該提到這是性能至關重要的部分。

+1

查看深入克隆:http://stackoverflow.com/questions/78536/deep-cloning-objects – 2014-12-04 12:45:19

+0

我正在考慮做類似的事情,但這似乎對我的遊戲來說很小,對於我的遊戲來說這將會很小設備和克隆可以發生4-5次,其次是其他算法..我應該指出,我還需要一個性能明智的解決方案 – 2014-12-04 12:49:57

+0

@MamaTate:性能不是一個問題,當它被複制幾次。 – 2014-12-04 12:53:18

回答

3

考慮到性能是您代碼中的主要問題,我不會使用自動深層克隆技術。相反,我建議使用C#中提供的最有效的內存克隆技術,Object.MemberWiseClone()see the MSDN page here)。這種方法幾乎是API的封裝,它直接複製引用的內存塊,並使整個過程閃電般快速。這種技術唯一的警告是它創建一個淺拷貝。也就是說,對象中的引用類型仍然會指向同一個實例。爲了正確處理這個問題,你需要一點額外的工作。

public interface IDeepCloneable<T> 
{ 
    T DeepClone(); 
} 

class Foo : IDeepCloneable<Foo> 
{ 
    Foo DeepClone() 
    { 
     // The simplest usecase 
     return (Foo)this.MemberWiseClone(); 
    } 
} 

class Bar : IDeepCloneable<Bar> 
{ 
    private Foo _foo; 
    private List<Foo> _lists; 
    private List<int> _valueTypedLists; 

    Bar DeepClone() 
    { 
     var clone = (Bar)this.MemberWiseClone(); 

     // This makes sure that deeper references are also cloned. 
     clone._foo = _foo.DeepClone(); 

     // Though you still need to manually clone types that you do not own like 
     // lists but you can also turn this into an extension method if you want. 
     clone._lists = _lists.Select(f => f.DeepClone()).ToList(); 

     // And you can simply call the ToList/ToArray method for lists/arrays 
     // of value type entities. 
     clone._valueTypedLists = _valueTypedLists.ToList(); 
     return clone; 
    } 
} 

我做了一些基準來比較這技術,在上述意見中提出的二進制序列的技術。下面是結果:

1 000 000 objects composed of 4 ints 
    Binary Serializer : 10.361799 seconds. 
    MemberWiseClone : 0.080879 seconds. (128x gain) 

1 000 000 objects composed of 4 Lists<int> with 4 items (16 ints + 4 List) 
    Binary Serializer : 47.288164 seconds. 
    MemberWiseClone : 0.517383 seconds. (91x gain) 

PS:你可能已經注意到,我用我自己的接口,而不是System.ICloneable。這是因爲.NET 2.0時代的內置接口日期,當泛型不可用時。它也有一個重要的警告,因爲它沒有正確說明它的意圖。基本上,沒有辦法知道克隆方法會產生什麼結果。它是淺拷貝還是深拷貝,甚至是同一類型的拷貝?沒有辦法確定。這就是爲什麼我建議實現您自己的IDeepCloneable和IShallowCloneable接口。