如果我們將代碼中的第1*處修改成:
oldObjList := TObjectList.Create(False);
將產生如下結果:
圖4
相對於TObjectList<T>,沒有Create(AOwnsObjects: Boolean)方式的重載,我們如何才能讓TObjectList<T>“不擁有”對象,當TObjectList<T>中的元素重新賦值、TObjectList<T>集合對象銷毀的時候,怎樣能保證裡面的舊元素不進行銷毀操作呢?答案是:不能。
四:TList<T>和TObjectList<T>的區別
如果將上面代碼的objList對象聲明時改成TList<TFelix>類型,並將第2*處代碼改成objList := TList<TFelix>.Create;結果就和使用TObjectList(圖4)的效果一樣了,當調用方法SetItem或者集合被銷毀後,舊元素或者內部的元素不會被銷毀。
原因在於,TObjectList<T>從TList<T>繼承而來,只重寫了Notify方法,此方法在集合內元素改變(指針變換、刪除、添加)等操作時調用。
請閱讀Generics.Collections.pas文件第1236行,TObjectList<T>重寫了Notify方法後,先調用了超類的Notify方法,然後判斷操作如果為cnRemoved則將元素.Free,所以元素在此處被析構。
五:後記
使用TObjectList<T>會將對象自動銷毀,使用TList<T>不會將對象自動銷毀。
受SymBian編程的影響,我習慣於對象自己創建、對象自己銷毀,特別是在使用對象集合類,有時候一個對象可能在這個集合內,同時又在另外一個集合內。如果TObjectList<T>把對象銷毀了,在另外一個集合內使用對象會造成不可預料的後果,所以建議大家不要使用TObjectList<T>。
其他幾個泛型類TDictionary<>等,方法和代碼都和.Net的類似,看了看代碼,真是讓人遐想連篇,此處不再介紹。