Έχω μια γενική λίστα αντικειμένων σε C# και επιθυμώ να κλωνοποιήσω τη λίστα. Τα αντικείμενα εντός της λίστας μπορούν να κλωνοποιηθούν, αλλά δεν φαίνεται να υπάρχει επιλογή για να κάνω list.Clone()
.
Υπάρχει κάποιος εύκολος τρόπος για να το παρακάμψετε αυτό;
Αν τα στοιχεία σας είναι τύποι τιμών, τότε μπορείτε απλά να κάνετε:
List<YourType> newList = new List<YourType>(oldList);
Ωστόσο, αν είναι τύποι αναφοράς και θέλετε ένα βαθύ αντίγραφο (υποθέτοντας ότι τα στοιχεία σας υλοποιούν σωστά το ICloneable
), θα μπορούσατε να κάνετε κάτι τέτοιο:
List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);
oldList.ForEach((item) =>
{
newList.Add((ICloneable)item.Clone());
});
Προφανώς, αντικαταστήστε το ICloneable
στα παραπάνω generics και κάντε cast με οποιονδήποτε τύπο στοιχείου σας που υλοποιεί το ICloneable
.
Αν ο τύπος του στοιχείου σας δεν υποστηρίζει το ICloneable
αλλά έχει έναν κατασκευαστή αντιγραφής, μπορείτε να κάνετε αυτό αντί αυτού:
List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);
oldList.ForEach((item)=>
{
newList.Add(new YourType(item));
});
Προσωπικά, θα απέφευγα το ICloneable
λόγω της ανάγκης να εγγυηθείτε ένα βαθύ αντίγραφο όλων των μελών. Αντ' αυτού, θα πρότεινα τον copy-constructor ή μια εργοστασιακή μέθοδο όπως YourType.CopyFrom(YourType itemToCopy)
που επιστρέφει μια νέα περίπτωση του YourType
.
Οποιαδήποτε από αυτές τις επιλογές θα μπορούσε να περιτυλιχθεί από μια μέθοδο (επέκταση ή όχι).
Για ένα ρηχό αντίγραφο, μπορείτε να χρησιμοποιήσετε τη μέθοδο GetRange της γενικής κλάσης List.
List<int> oldList = new List<int>( );
// Populate oldList...
List<int> newList = oldList.GetRange(0, oldList.Count);
Παρατίθεται από: [Generics Recipes][1]
[1]: https://web.archive.org/web/20121230023705/http://en.csharp-online.net/CSharp_Generics_Recipes%E2%80%94Replacing_the_ArrayList_with_Its_Generic_Counterpart "C# Generics Recipes",
Αν σας ενδιαφέρουν μόνο οι τύποι τιμών...
Και γνωρίζετε τον τύπο:
List<int> newList = new List<int>(oldList);
Αν δεν γνωρίζετε τον τύπο από πριν, θα χρειαστείτε μια βοηθητική συνάρτηση:
List<T> Clone<T>(IEnumerable<T> oldList)
{
return newList = new List<T>(oldList);
}
Η just:
List<string> myNewList = Clone(myOldList);