Πώς μπορώ να κλωνοποιήσω μια γενική λίστα στη C#;

Έχω μια γενική λίστα αντικειμένων σε C# και επιθυμώ να κλωνοποιήσω τη λίστα. Τα αντικείμενα εντός της λίστας μπορούν να κλωνοποιηθούν, αλλά δεν φαίνεται να υπάρχει επιλογή για να κάνω list.Clone().

Υπάρχει κάποιος εύκολος τρόπος για να το παρακάμψετε αυτό;

Αν τα στοιχεία σας είναι τύποι τιμών, τότε μπορείτε απλά να κάνετε:

List newList = new List(oldList);

Ωστόσο, αν είναι τύποι αναφοράς και θέλετε ένα βαθύ αντίγραφο (υποθέτοντας ότι τα στοιχεία σας υλοποιούν σωστά το ICloneable), θα μπορούσατε να κάνετε κάτι τέτοιο:

List oldList = new List();
List newList = new List(oldList.Count);

oldList.ForEach((item) =>
    {
        newList.Add((ICloneable)item.Clone());
    });

Προφανώς, αντικαταστήστε το ICloneable στα παραπάνω generics και κάντε cast με οποιονδήποτε τύπο στοιχείου σας που υλοποιεί το ICloneable.

Αν ο τύπος του στοιχείου σας δεν υποστηρίζει το ICloneable αλλά έχει έναν κατασκευαστή αντιγραφής, μπορείτε να κάνετε αυτό αντί αυτού:

List oldList = new List();
List newList = new List(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });

Προσωπικά, θα απέφευγα το ICloneable λόγω της ανάγκης να εγγυηθείτε ένα βαθύ αντίγραφο όλων των μελών. Αντ' αυτού, θα πρότεινα τον copy-constructor ή μια εργοστασιακή μέθοδο όπως YourType.CopyFrom(YourType itemToCopy) που επιστρέφει μια νέα περίπτωση του YourType.

Οποιαδήποτε από αυτές τις επιλογές θα μπορούσε να περιτυλιχθεί από μια μέθοδο (επέκταση ή όχι).

Σχόλια (21)

Για ένα ρηχό αντίγραφο, μπορείτε να χρησιμοποιήσετε τη μέθοδο GetRange της γενικής κλάσης List.

List oldList = new List( );
// Populate oldList...

List 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&quot,

Σχόλια (2)

Αν σας ενδιαφέρουν μόνο οι τύποι τιμών...

Και γνωρίζετε τον τύπο:

List newList = new List(oldList);

Αν δεν γνωρίζετε τον τύπο από πριν, θα χρειαστείτε μια βοηθητική συνάρτηση:

List Clone(IEnumerable oldList)
{
    return newList = new List(oldList);
}

Η just:

List myNewList = Clone(myOldList);
Σχόλια (2)