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

 

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

Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

Îåêßíçóå áðü ôï ìÝëïò tnec. Τελευταία δημοσίευση από το μέλος tnec στις 16-03-2006, 17:31. Υπάρχουν 6 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  13-03-2006, 19:34 10609

    Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

    Λοιπόν έχω το εξής "απίστευτο" πρόβλημα. Έχω μια συνάρτηση που δέχεται σαν όρισμα μια λίστα τύπου generic.List(Of T) όπου T είναι μια δική μου κλάση μόνο με properties. Η συνάρτηση θέλω να επιστρέφει μια νέα λίστα την οποία δημιουργεί με βάση το όρισμα. Πιο συγκεκριμένα, η κάθε λίστα αντιπροσωπεύει μια κατάσταση σε ένα παιχνίδι, και η συνάρτηση πρέπει να δέχεται μια κατάσταση και να παράγει μια καινούρια. Το πρόβλημα είναι ότι δεν θέλω να χάνω την παλιά κατάσταση. Η συνάρτησή μου μέσα της δημιουργεί μια νέα λίστα, την γεμίζει (AddRange) με τα στοιχεία του ορίσματος και κάνει πράξεις. Το πρόβλημα είναι ότι όταν "γεμίζω" τη νέα λίστα με τα στοιχεία αυτής που περνάω ByVal στο όρισμα, η VB αντιγράφει μόνο τους δείκτες, με αποτέλεσμα, ΟΤΙ ΑΛΛΑΓΗ ΚΑΝΩ στην τοπική νέα λίστα, περνάει προφανώς στη λίστα πίσω από το όρισμα, και την καταστρέφει. Το θέμα είναι ότι χρειάζομαι ένα τρόπο για να μην πειράζει το όρισμα, δηλαδή θέλω να δημιουργεί νέο ανεξάρτητο αντίγραφο του ορίσματος στη μνήμη. Δηλαδή έχω:

    Λίστα1 -> θέλω να μην την πειράξει κανένας, περνάει σαν όρισμα στη συνάρτηση (ας πούμε διεύθυνση 1-100 στη μνήμη)
    Λίστα2 -> την δημιουργεί τοπικά η συνάρτηση για να κάνει πράξεις πάνω της και να την επιτρέφει με return Λίστα2 (ας πούμε διεύθυνση 101-200)

    Πώς θα γεμίσω την Λίστα2 με στοιχεία ίδια με αυτά της Λίστας1? Δοκίμασα Λιστα2=Λίστα1 και Λίστα2.AddRange(Λίστα1) και Λίστα2=new list(Of T)(Λιστα1) και γεμίζει τις θέσεις 101-200 με δείκτες στις θέσεις 1-100, κάτι που δεν θέλω. ΔΕΝ ΥΠΑΡΧΕΙ ΤΡΟΠΟΣ ΝΑ ΠΕΡΑΣΩ ΠΡΑΓΜΑΤΙΚΟ ΑΝΤΙΓΡΑΦΟ ΤΟΥ ΟΡΙΣΜΑΤΟΣ ΚΑΙ ΟΧΙ ΔΕΙΚΤΗ ΣΕ ΑΥΤΟ?????????????

    Οποιαδήποτε βοήθεια είναι ευπρόσδεκτη.

    Υ.Γ. Η Λίστα1 γεμίσει με μία procedure. Το να φτιάχνω από την αρχή πολλές ίδιες λίστες και μετά να τις περνάω (σαν δείκτη) στη συνάρτηση, δεν είναι πρακτικό, γιατί όπως έγραψα παραπάνω κάθε λίστα αντιπροσωπεύει μια διάταση-instance ενός παιχνιδιού, οπότε αν το κάνω έτσι θα είναι:

    1ο βήμα->Λίστα1
    2ο βήμα->function(Λίστα2)
    3ο βήμα->function(function(Λίστα3))   κ.ο.κ και οι Λίστα1,Λίστα2,Λίστα3 κλπ φτιάχνονται αρχικά ίδιες

    οπότε αν έχω 300 βήματα στο παιχνίδι, θα γίνεται χαμός. ΓΙ ΑΥΤΟ ΑΝΑΖΗΤΩ ΤΡΟΠΟ να φτιάχνω επιτόπου αντίγραφο του ορίσματος και να καλώ

    NextStep=function(ThisStep), χωρίς να μου χαλάει το ThisStep

     

  •  13-03-2006, 20:38 10611 σε απάντηση της 10609

    Απ: Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

    Αν υλοποιήσεις μια Clone μέθοδο για την κλάση Τ, στο οποίο επιστρέφεις ένα deep ή shallow copy του αντικειμένου, και μέσα στη function να δημιουργείς μία καινούρια list με τα αντίγραφα των αντικειμένων της λίστας;
    Dimitris-Ilias Gkanatsios
    Developer Evangelist, Microsoft Hellas

    My Blog
    StudentGuru
    Twitter
    Facebook
  •  13-03-2006, 20:47 10612 σε απάντηση της 10609

    Απ: Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

    Ωραία, αλλά πως κάνω ένα deep copy του αντικειμένου? Πως το φτιάχνω? Άμα κάνω Implement το IClonable και φτιάξω μια clone, το μόνο που γίνεται είναι Me.MemberwiseClone() (το object δεν έχει άλλη έτοιμη μέθοδο). Αλλά το MemberwiseClone για τα references αντιγράφει pointers!!!! Οπότε πέφτω πάλι στα ίδια
  •  14-03-2006, 05:34 10613 σε απάντηση της 10609

    Απ: Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

    Μπορείς να αλλάξεις την custom κλάση σου σε struct. Από εκεί και πέρα, αντιγράφοντας τα structs αυτά από το ένα σημείο στο άλλο (προσοχή, όχι αντιγράφοντας τη λίστα που τα εμπεριέχει!), θα δημιουργηθούν αντίγραφα τους, και δε θα αντιγραφούν τα references.



    Μια άλλη λύση που μου έρχεται στο μυαλό, αλλά είναι λίγο Overkill, έχει ως εξής: Ποια μέθοδος δημιουργεί σίγουρα αντίγραφα των δεδομένων σου; Το Serialization! Θα μπορούσες δηλαδή να κάνεις serialize και deserialize σε νέα λίστα, μέσω MemoryStream.


    Μου φαίνεται όμως ότι η πρώτη λύση είναι και η πιο λογική (Νομίζω ωστόσο ότι το πρόβλημα αυτό το έχω ξανασυναντήσει, όταν έριχνα μια ματιά στο Prototype pattern).
    Μην αφήνετε τα media να σας "ταΐζουν"!
  •  14-03-2006, 12:01 10628 σε απάντηση της 10609

    Απ: Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

    Σας ευχαριστώ όλους για τις απαντήσεις σας. Το παραπάνω πρόβλημα προέκυψε δυστυχώς αφού είχα σχεδιάσει όλη την εφαρμογή, οπότε αν δεν υπάρχει κάποια "απλή" - άμεση λύση θα αναγκαστώ να αλλάξω όλη τη φιλοσοφία της ώστε να γίνει αυτό που λέμε σωστή δουλειά, και όχι μπαλώματα. Δηλαδή αντί για copy contractors κλπ που θέλουν χρόνο, νομίζω η διαφορετική σχεδίαση είναι πιο καλή λύση.

    Αυτό που θα με διευκόλυνε είναι να πω στη VB να περάσει αντίγραφο και όχι reference. Τελοσπάντων, αν δεν υπάρχει λύσει, δεν θα χάσουμε και τον ύπνο μας :)
  •  14-03-2006, 23:49 10663 σε απάντηση της 10609

    Απ: Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

    σε μια κλάση που κάνεις implement to ICloneable interface, υλοποιείς το deep copy ως εξής: (δεν είναι δύσκολη η μετατροπή σε VB)

    #region ICloneable Members
    public object Clone()
    {
    MemoryStream buffer = new MemoryStream();
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(buffer,this);
    buffer.Position = 0;
    return formatter.Deserialize(buffer);
    }
    #endregion


    Dimitris-Ilias Gkanatsios
    Developer Evangelist, Microsoft Hellas

    My Blog
    StudentGuru
    Twitter
    Facebook
  •  16-03-2006, 17:31 10720 σε απάντηση της 10609

    Απ: Πέρασμα ByVal παραμέτρου τύπου Generic.List(Of T) - ΓΙΝΕΤΑΙ????????

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