2010-04-30 14 views
8

मेरे पास विभिन्न ऑब्जेक्ट प्रकारों के विभिन्न पर्यवेक्षण चयन हैं। मैं एक ऐसी विधि लिखना चाहूंगा जो इनमें से किसी भी ऑब्जेक्ट प्रकार का संग्रह ले ले और एक नया संग्रह लौटाए, जहां प्रत्येक तत्व दिए गए संग्रह में तत्वों की गहरी प्रति है। यहाँ एक specifc वर्गसंग्रह में सभी तत्वों की गहरी प्रतिलिपि बनाने के लिए सामान्य विधि

private static ObservableCollection<PropertyValueRow> DeepCopy(ObservableCollection<PropertyValueRow> list) 
    { 
     ObservableCollection<PropertyValueRow> newList = new ObservableCollection<PropertyValueRow>(); 
     foreach (PropertyValueRow rec in list) 
     { 
      newList.Add((PropertyValueRow)rec.Clone()); 
     } 
     return newList; 
    } 

के लिए एक उदाहरण मैं किसी भी वर्ग जो ICloneable लागू करता है के लिए इस विधि सामान्य बना सकते हैं कैसी है?

+4

एक उचित चेतावनी के रूप में, सभी आईसीएलनेबल कार्यान्वयन वास्तव में गहरी प्रतियां नहीं हैं। –

उत्तर

24

आप कुछ इस तरह कर सकता है:

private static ObservableCollection<T> DeepCopy<T>(ObservableCollection<T> list) 
    where T : ICloneable 
{ 
    ObservableCollection<T> newList = new ObservableCollection<T>(); 
    foreach (T rec in list) 
    { 
     newList.Add((T)rec.Clone()); 
    } 
    return newList; 
} 

ध्यान दें कि आप IEnumerable<T> लेने के द्वारा इस को अधिक सामान्य बनाना सकता है, और LINQ यह और भी आसान बना देता है:

private static ObservableCollection<T> DeepCopy<T>(IEnumerable<T> list) 
    where T : ICloneable 
{ 
    return new ObservableCollection<T>(list.Select(x => x.Clone()).Cast<T>()); 
} 
+1

मैंने कोशिश की थी, लेकिन ऐसा लगता है कि एक सामान्य विधि नहीं है। मुझे "गैर-सामान्य घोषणाओं पर बाधाओं की अनुमति नहीं है" संकलक त्रुटि प्राप्त होती है। – bwarner

+1

ओह - मेरे पास एक टाइपो था; विधि नाम के अंत में आपको बस ' 'की आवश्यकता है। –

+1

जॉन स्कीट के बारे में इन सभी चक नॉरिस-प्रकार चुटकुले को पढ़कर, मुझे विश्वास करना बहुत मुश्किल लगता है - कि जॉन स्कीट के पास उनके पद में एक टाइपो था। लेकिन वास्तव में एक सुंदर पोस्ट। साफ दूसरे LINQ- आधारित संस्करण के लिए धन्यवाद। साफ। बहुत साफ़। –

3
private static ObservableCollection<T> DeepCopy<T>(ObservableCollection<T> list) 
    where T : ICloneable 
{ 
    ObservableCollection<T> newList = new ObservableCollection<T>(); 
    foreach (T rec in list) 
    { 
     newList.Add((T)rec.Clone()); 
    } 
    return newList; 
} 
+2

यह जॉन स्कीट के पोस्ट का "क्लोन" संस्करण प्रतीत होता है :-) –

+8

आपको लगता है कि मैंने 13:26 पर सही संस्करण में एक कोड को "क्लोन" किया था जब उसने 14:15 पर इसे सही किया था ... मैं नहीं करता एक समय मशीन नहीं है। टाइम मशीन के लिए – Hinek

+0

+1 :) – WiiMaxx

0

मैं एक का उपयोग करें बहुत ही समान कार्य जो सभी आईसीओलेक्शन के साथ काम करता है जिसे बनाया जा सकता है (उदाहरण के लिए कई मानक संग्रह):

public static TContainer CloneDeep<TContainer, T>(TContainer r) 
     where T : ICloneable 
     where TContainer: ICollection<T>, new() 
    { 
     // could use linq here, but this is my original pedestrian code ;-) 
     TContainer l = new TContainer(); 
     foreach(var t in r) 
     { 
      l.Add((T)t.Clone()); 
     } 

     return l; 
    } 

दुर्भाग्यवश संकलक प्रकारों को कम करने में सक्षम नहीं है ताकि किसी को स्पष्ट रूप से उन्हें पास कर सकें। एक मुट्ठी भर से अधिक कॉल के लिए मैं एक विशेषज्ञता लिखता हूं। यहां सूची के लिए एक उदाहरण दिया गया है (जिसे स्वयं को पूरी तरह से टी के साथ बुलाया जा सकता है)।

public static List<T> CloneListDeep<T>(List<T> r) where T : ICloneable 
    { 
     return CloneDeep<List<T>, T>(r); 
    } 

मैं क्रम में बड़े पैमाने पर इस सुविधा का उपयोग संवादों पर datagridviews जो रद्द किया जा सकता के लिए datasources के रूप में सेवारत सूचियों की प्रतियां बनाने के लिए। संवाद रद्द होने पर संशोधित सूची को त्याग दिया जाता है; जब संवाद ठीक हो जाता है तो संपादित सूची बस मूल को बदल देती है। इस पैटर्न के लिए अनिवार्य है, निश्चित रूप से, एक semantically सही और अच्छी तरह से बनाए रखने के लिए T.clone() है।

संबंधित मुद्दे