Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Clone your objects ...

Îåêßíçóå áðü ôï ìÝëïò anjelinio. Τελευταία δημοσίευση από το μέλος anjelinio στις 03-10-2005, 10:57. Υπάρχουν 0 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  03-10-2005, 10:57 5837

    Clone your objects ...

    Καλημέρα παιδιά.

    Καιρό τώρα, ήθελα ένα standard τρόπο να έχω μια μέθοδο Clone() στα αντικείμενά μου, η οποία με αυτόματο τρόπο θα μου δημιουργεί ένα clone ενός instance μιας κλάσσης μου. Κατέληξα σε 2 τρόπους, καθένας με τα καλά και τα κακά του, του οποίους παραθέτω εδώ, ως τροφή για σχόλια και απόψεις ...

    Τρόπος 1. Κάνω inherit απο την κλάσση CloneableObject, ( η οποία δημιουργεί κλώνους ενός object graph, όπου τα 'παιδιά'  είναι είτε value types ή ClonableObject's κι αυτά ... )

    public abstract class CloneableObject

           {

                  public object Clone(){

                         // Get the 'running' type

                         Type childType = this.GetType();//MethodInfo.GetCurrentMethod().ReflectedType;

                         // ok, create a new instance of the reflected type

                         // get the default no-args constructor first, and then invoke

                         ConstructorInfo constructor = childType.GetConstructor(new Type[0]);

                         object _instance = constructor.Invoke(null);

     

                         // get references to all the properties and fields, and call each one

                         PropertyInfo[] properties = childType.GetProperties();

                         FieldInfo[] fields = childType.GetFields();

     

                         // cool so far .. now loop through the properties & fields, get the values of 'this', and

                         // set the values to the new instance... phew !

                         foreach(PropertyInfo pInfo in properties){

                               object pValue = pInfo.GetValue(this, null);

                               object thePValue = (pValue is CloneableObject)? ((CloneableObject)pValue).Clone() : pValue;

                               pInfo.SetValue(_instance, thePValue, null);

                         }

     

                         foreach(FieldInfo fInfo in fields){

                               object fValue = fInfo.GetValue(this);

                               object theFValue = (fValue is CloneableObject)? ((CloneableObject)fValue).Clone() : fValue;

                               fInfo.SetValue(_instance, theFValue);

                         }

     

                         return _instance;

                  }

           }

    Τρόπος 2. Κάνω inherit απ'την κλάσση BinaryCloneableObject, η οποία χρησιμοποιεί Binary Serialization για να δημιουργήσει μια κόπια του current instance. Αυτό δουλεύει μόνο αν στην εκάστοτε κλάσση μαρκάρω ως [Serializable] ...

    [Serializable]

           public abstract class BinaryCloneableObject

           {

                  public object Clone(){

                         // Serialize the object in memory ...

                         IFormatter formater = new BinaryFormatter();

                         MemoryStream memoryBuffer = new MemoryStream();

                         formater.Serialize(memoryBuffer, this);

                         // 'rewind' the stream

                         memoryBuffer.Position = 0;

                         // Deserialize into an object ...

                         return formater.Deserialize(memoryBuffer);

                  }

           }


    .. και για να το τεστάρω ως απόδωση, έγραψα αυτό το προγραμματάκι το οποίο κάνει κλώνους απο 2 κλάσσεις (και οι 2 έχουν απλώς ένα member string με τιμή "my_string") 1000 φορές, και δείχνει στην οθόνη το μέσο όρο σε ticks για κάθε κλώνο ...

    static void Main(string[] args)

                  {

                         long tst1Time = 0;

                         long tst2Time = 0;

     

                         for(int i=0; i<1000; i++){

                               Test1 tst1 = new Test1();

                               Test2 tst2 = new Test2();

     

                               long startTime = DateTime.Now.Ticks;

                               Test1 _tst1 = (Test1)tst1.Clone();

                               long endTime = DateTime.Now.Ticks;

     

                               tst1Time += endTime - startTime;

     

                               startTime = DateTime.Now.Ticks;

                               Test2 _tst2 = (Test2)tst2.Clone();

                               endTime = DateTime.Now.Ticks;

     

                               tst2Time += endTime - startTime;

                         }

     

                         Console.WriteLine("Test 1: {0}", tst1Time/1000);

                         Console.WriteLine("Test 2: {0}", tst2Time/1000);

     

                         Console.ReadLine();

                  }

    ... παραδόξως ... η μέθοδος χωρίς το binary serialization φαίνεται να είναι πιο γρήγορη στην πλειοψηφία των test runs που έτρεξα ( 5-10 έτρεξα, μην αγχωνόμαστε Δευτεριάτικα ... ) , και αν και κάποιες φορές ήταν πιο αργή, αυτή ήταν μια στις 5 περίπου ... τυπικά, η μέθοδος χωρίς το binary serialization ήταν απο 200 έως και 781 (!!!) ticks πιο γρήγορη απ'την άλλη ...

    Δεν ξέρω γιατί συνέβη αυτό (είναι όντως τόσο πιο βαρύ το serialization??), και γιατί ο ένας τρόπος είναι πιο γρήγορος απ'τον άλλο ( κι ακόμη δεν είμαι πεπεισμένος οτι είναι όντως πιο γρήγορος .. ) γι'αυτό και παραθέτω εδώ αυτό το post για να το .. φιλοσοφήσουμε το θέμα :)

    Καλή μας μέρα



    Angel
    O:]
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems