2011-08-02 62 views
4

我有以下幾點:如何使用ICloneable <T>當T是列表<T>?

public class InstanceList : List<Instance> {} 

我想使這個可複製的。這裏繼例如:Why no ICloneable<T>?

我試過如下:

public interface ICloneable<T> : ICloneable Where T : ICloneable<T> 
      {  new T Clone(); } 

    public class InstanceList : List<Instance>, ICloneable<List<Instance>> {} 

但我得到一個編譯錯誤。該錯誤消息指出 List<Instance> 必須爲了使用參數T在通用接口 ICloneable<T>轉換爲 ICloneable<List<Instance>>

我在這裏錯過了什麼?

回答

4

你不能這樣做,因爲你不能定義List<T>自己。如果您可以聲明自己的List<T>,那麼您將只能這樣做,因爲您限制的方式爲ICloneable<T>。由於List<T>確實不會實現ICloneable<T>,因此您將不得不將T的類型替換爲InstanceList,您可以使用執行的控制。

這裏是你將如何實現它:

public class InstanceList : List<Instance>, ICloneable<InstanceList> 
{ 
    public InstanceList Clone() 
    { 
     // Implement cloning guts here. 
    } 

    object ICloneable.Clone() 
    { 
     return ((ICloneable<InstanceList>) this).Clone(); 
    } 
} 

public class Instance 
{ 

} 

public interface ICloneable<T> : ICloneable where T : ICloneable<T> 
{ 
    new T Clone(); 
} 

當然,還有另外一種選擇,你可以做。你可以擴大你的泛型一點點,創建一個CloneableList<T>類型:

public class CloneableList<T> : List<T>, ICloneable<CloneableList<T>> 
{ 
    public CloneableList<T> Clone() 
    { 
     throw new InvalidOperationException(); 
    } 

    object ICloneable.Clone() 
    { 
     return ((ICloneable<CloneableList<T>>) this).Clone(); 
    } 
} 

public interface ICloneable<T> : ICloneable where T : ICloneable<T> 
{ 
    new T Clone(); 
} 

如果你真的想獲得幻想,創造一些限制噸至ICloneable。然後,您可以在Instance類上實現ICloneable,並且可以在ICloneable<T>列表中包含任何其他內容,從而以完全相同的方式處理每個CloneableList<T>,從而爲您要創建的每個可複製列表避免不同的ICloneable<T>實現。

public class CloneableList<T> : List<T>, ICloneable<CloneableList<T>> where T : ICloneable 
{ 
    public CloneableList<T> Clone() 
    { 
     var result = new CloneableList<T>(); 
     result.AddRange(this.Select(item => (T) item.Clone())); 
     return result; 
    } 

    object ICloneable.Clone() 
    { 
     return ((ICloneable<CloneableList<T>>) this).Clone(); 
    } 
} 

public interface ICloneable<T> : ICloneable where T : ICloneable<T> 
{ 
    new T Clone(); 
} 
+0

這工作。一個變化:T克隆();需要新的關鍵字來覆蓋object.Clone()。我現在看到我的想法是不正確的。我克隆的類別不是列表。謝謝! – sapbucket

+0

請務必查看我所做的修改。第二個和第三個選項比我列出的第一個選項靈活得多。 –

+0

爲什麼它需要第二個對象ICloneable.Clone()方法?我認爲這個接口只需要一個Clone()操作的方法。 – sapbucket

2

問題是您的通用約束where T : IClonable<T>。因爲「實例化」您的界面爲ICloneable<List<Instance>>,所以List<Instance>是您的T,所以通用約束轉換爲where List<Instance> : IClonable<List<Instance>>List<Instance>不符合該限制。

也許你正在試圖做這樣的事情:

public interface ICloneableList<T> : ICloneable where T : ICloneable 
{ 
} 
+0

如果我這樣做,這樣我得到'公共類InstanceList:列表,ICloneable {公共對象的clone(){}}」 – sapbucket

+0

...並返回類型爲對象,而不是類型列表 sapbucket

+0

我省略了方法,但它仍然需要它。我只是指出通用約束是錯誤的。 – Jacob

1

要添加到其他好的答案已經存在 - 當你克隆,你希望得到一個相同的拷貝過來的,對不對?因此,而不是:

public class InstanceList : List<Instance>, ICloneable<List<Instance>> {} 

難道不應該實際上是:

public class InstanceList : List<Instance>, ICloneable<InstanceList> {} 

這樣,你也不會得到編譯器錯誤。

+0

沒錯,那是解決錯誤的答案。本着社區的精神,我認爲David給我展示了一個更好的實現方式,他最初指出了你上面展示的內容。 – sapbucket

0

我不認爲你真的可以做你想做的。雖然有必要不要求ICloneable的類型參數實現ICloneable <T>,但我不認爲List可以很好地擴展以支持克隆,因爲它不提供任何分離方法或者複製包含所有數據項的數組,不允許子類訪問該數組,並且不允許子類重寫足夠的虛擬方法來呈現數組。雖然克隆方法應該使用MemberwiseClone開始(爲了確保克隆的對象與原始對象類型相同),但不會保證強制新克隆的列表創建一個新的數組來保存它的對象而不會干擾舊的一。

我可以建議做你想要將定義一個ICloneableList <牛逼>其自IList <牛逼>和ICloneable < IList的<牛逼> >繼承並定義一個CloneableList類implementats什麼最接近的事,通過包裝一名單。克隆一個CloneableList應該創建一個新的列表<T>,從舊的列表複製項目,這可以通過使用適當的新列表構造函數來完成。