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

 

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

Stack

Îåêßíçóå áðü ôï ìÝëïò Alexander. Τελευταία δημοσίευση από το μέλος Alexander στις 16-01-2008, 14:15. Υπάρχουν 9 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  15-01-2008, 17:53 39212

    Stack

    Καλησπέρα,
    Έχω ένα προβληματάκι - απορία.
    Έχω μια κλάση, και γεμίζω μια στοίβα με αντικείμενά της. Μετά, θέλω να δω τι είναι το πάνω-πάνω στοιχείο. Κάνω λοιπόν το εξής:

    Class1 next;
    next = stack.Peek();

    Και μου βγάζει αυτό το λάθος:
    Use of anassigned local variable 'next'

    Αν κάνω αυτό, δουλεύει μια χαρά:

    Class1 next = new Class1();
    next = stack.Peek();

    Στη δεύτερη περίπτωση δημιουργήθηκε άλλο ένα αντικείμενο Class1, έτσι; Πώς μπορώ να το αποφύγω αυτό;

    Ευχαριστώ
  •  15-01-2008, 18:38 39213 σε απάντηση της 39212

    Απ: Stack

    Αν κατάλαβα καλά την ερώτηση κάτι τέτοιο φνατάζομαι ότι θα σε βοηθούσε:

    Class1 next = stack.Peek();

    υπό την προηπόθεση ότι τα αντικείμενα μέσα στο stack είναι τύπου Class1.


    MSc Konstantinos Pantos
    MCP Software Engineer
    http://blog.pantos.name
    http://kostas.pantos.name
  •  15-01-2008, 19:00 39214 σε απάντηση της 39213

    Απ: Stack

    όχι, δε βοηθάει, γιατί δηλώνω πρώτα το next, και μετά ακολουθεί ένα if - else για να δω που ακριβώς θα δείχνει.
    Αλλά αυτό δεν είναι ίδιο με το

    Class1 next;
    next = stack.Peek();
  •  15-01-2008, 22:44 39218 σε απάντηση της 39214

    Απ: Stack

    Στον κώδικά σου πρέπει να εξασφαλίσεις ότι οπουδήποτε, πριν διαβάσεις το αντικείμενο next, πρέπει να του έχεις δώσει μια τιμή.

    Αυτό σημαίνει και το μήνυμα λάθους που σου βγαίνει. Εν τέλει, αυτό καμμία σχέση δεν έχει με το stack.

    Αν δώσεις στην αρχή Class1 next = null; -και το αλλάζεις έπειτα όταν και όπου θέλεις- δεν θα έχεις πρόβλημα.

    Μόνο βεβαιὠσου ότι χειρίζεσαι σωστά την περίπτωση που έχει μένει το null.

     


    Βαγγέλης Λαμπρινίδης.
  •  15-01-2008, 22:48 39219 σε απάντηση της 39214

    Απ: Stack

    Οι δύο κλήσεις είναι απολύτως ταυτόσημες. Αυτό μπορείς να το δεις και αν κοιτάξεις το il που δημιουργείται για τις δύο κλήσεις, ο οποίος είναι ακριβώς ο ίδιος. Για τον παρακάτω κώδικα:

    Stack stack = new Stack();
    stack.Push(new Class1());

    Class1 next;
    next = (Class1)stack.Peek();

    Class1 next2 = (Class1)stack.Peek();

    Δημιουργείται το παρακάτω IL:

    .maxstack 2
    .locals init (
    [0] class [mscorlib]System.Collections.Stack stack,
    [1] class StackTest.Class1 next,
    [2] class StackTest.Class1 next2)
    L_0000: nop
    L_0001: newobj instance void [mscorlib]System.Collections.Stack::.ctor()
    L_0006: stloc.0
    L_0007: ldloc.0
    L_0008: newobj instance void StackTest.Class1::.ctor()
    L_000d: callvirt instance void [mscorlib]System.Collections.Stack::Push(object)
    L_0012: nop
    L_0013: ldloc.0
    L_0014: callvirt instance object [mscorlib]System.Collections.Stack::Peek()
    L_0019: castclass StackTest.Class1
    L_001e: stloc.1
    L_001f: ldloc.0
    L_0020: callvirt instance object [mscorlib]System.Collections.Stack::Peek()
    L_0025: castclass StackTest.Class1
    L_002a: stloc.2

    To next δημιουργείται στις γραμμές L_0013-L_001e ενώ το next2 στις γραμμές L_001f-L_002a. Όπως βλέπεις, ο κώδικας είναι ακριβώς ο ίδιος.

    Υποψιάζομαι ότι δεν έχει καταλάβει πως δουλεύουν οι κλάσεις και οι μεταβλητές. Για να δημιουργήσεις ένα καινούριο αντικείμενο της κλάσης Class1 πρέπει οπωσδήποτε να χρησιμοποιήσεις το keyword new. Υποψιάζομαι ότι στον κώδικα σου δεν έχεις κάνει new τη μεταβλητή stack γι αυτό και σου εμφανίζει το πρόβλημα. Πρέπει δηλαδή να γράψεις ό,τι γράφω κι εγώ στην πρώτη γραμμή του κώδικα. Όταν γράφεις Class1 next, απλά λες στον compiler ότι κάποια στιγμή θα φτιάξεις ένα αντικείμενο, χωρίς να το φτιάχνεις εκείνη τη στιγμή.

    Από εκεί και πέρα, είτε ορίσεις τη μεταβλητή σε μία γραμμή και της δώσεις τιμή στην επόμενη, είτε κάνεις και τα δύο βήματα στην ίδια γραμμή, ο κώδικας που δημιουργείται όπως είδες είναι ακριβώς ο ίδιος.


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  16-01-2008, 11:32 39229 σε απάντηση της 39219

    Απ: Stack

    Το new γίνεται σε κάποιο άλλο σημείο, αλλά γίνεται, και η στοίβα γεμίζει με νέα αντικείμενα. Η απορία μου είναι γιατί να πρέπει το next να αρχικοποιείται;  Με τον τρόπο που λες δηλαδή, δεν μου δουλεύει.

    Με Class1 next = null; όντως δουλεύει μια χαρά.

    Ξέχασα να αναφέρω κάτι, που ίσως να φταίει. Τα αντικείμενα που βρίσκονται στη στοίβα είναι αντικείμενα κλάσεων, που κληρονομούν μία πιο γενική. Το next είναι του τύπου της γενικής (και abstract) κλάσης. πχ

    public abstract class abstract_class { };

    public class Class1 : abstract_class{};

    public class Class2 : abstract_class{};

    H stack έχει είτε Class1 είτε Class2 αντικείμενα

    abstract_class next = null;

    next = stack.peek();


    η stack.peek() επιστρέφει αντικείμενα abstract_class (έχω φτιάξει μια δική μου κλάση Stack, και η peek είναι ιδιότητά της που απλώς κάνει το εξής: { return (abstract_class)_stack.Peek(); } )

  •  16-01-2008, 11:46 39232 σε απάντηση της 39229

    Απ: Stack

    Αν φτιάξεις ένα νέο πρόγραμμα και βάλεις μόνον τον κώδικα που σου έγραψα στην Main θα δεις ότι δουλεύει. Το ίδιο και αν φτιάξεις μία καθαρή φόρμα και στο Load της βάλεις μόνο τον κώδικα αυτό. Προφανώς κάνεις και άλλα πράγματα που δεν αναφέρεις. Αν δεν απομονώσεις όλο τον σχετικό κώδικα σε ένα σημείο και να μας τον δώσεις δεν θα βγάλουμε άκρη - όλο θα μαντεύουμε.

    Ο elam σωστά μάντεψε ότι μάλλον χρησιμοποιείς την next πριν την γραμμή στην οποία της δίνεις τιμή. Αυτό θα έχει σαν βέβαιο αποτέλεσμα ένα Null Reference Exception όταν εκτελέσεις τον κώδικα. O compiler της C# είναι αρκετά έξυπνος για να το καταλάβει αυτό και να σε ειδοποιήσει. Την ειδοποίηση την παρακάμπτεις θέτοντας μία οποιαδήποτε τιμή στη next όταν την ορίζεις, είτε null είτε ένα πραγματικό αντικείμενο.


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  16-01-2008, 12:20 39234 σε απάντηση της 39232

    Απ: Stack

    Οκ, πιο πολύ σαν απορία το είχα, γιατί τώρα μαθαίνω τη γλώσσα. Αυτό που κάνω (όσο πιο αναλυτικά γίνεται) είναι ότι έχω 2 αρχεία .cs, και στο ένα είναι η Main. Στο άλλο υπάρχει μια κλάση problem και μια συνάρτηση find_solution. Η problem έχει τη στοίβα. Στη Main λοιπόν δημιουργώ ένα αντικείμενο problem και δύο αντικείμενα (με new), τα οποία βάζω στη στοίβα του problem και καλώ την problem.find_solution(). Η find_solution, πρέπει να επεξεργαστεί τα αντικείμενα της στοίβας. Δημιουργεί στην αρχή το next, και μετά μπαίνει σε ένα while(!_stack.empty()){...}. Μέσα στο while πρώτα παίρνει το επόμενο στοιχείο της στοίβας, (με Peek() ή Pop()) και έπειτα κοιτάει να δει τι είναι. Εκεί μου βγάζει το λάθος, και μου υπογραμμίζει τα if όπου ελέγχω να δω τι γίνεται με το next.
  •  16-01-2008, 13:20 39238 σε απάντηση της 39234

    Απ: Stack

    Λίγος κώδικας = 1.000.000 λέξεις. Αν μας δείξεις την κλάση θα καταλάβουμε αμέσως. Αλλά η stack.empty()? Η μέθοδος empty υπάρχει στο stack της C++, όχι στο stack του .NET.

    Τώρα να υποθέσω ότι η στοίβα έχει οριστεί σαν πεδίο? Δηλαδή έχεις κάνει κάτι σαν αυτό?

    class Problem
    {
        public Stack stack;

        public object find_Solution()
        {
            while (stack.Count != 0)
            {
                Object next = stack.Pop();
                return next;
            }
            return null;
        }
    }

    Αν έχεις κάνει κάτι τέτοιο, και προσπαθείς να δώσεις τιμή στην stack από άλλη κλάση πράγματι θα πάρεις warning γιατί ο compiler δεν μπορεί να ξέρει ότι εσύ κάπου αλλού θα δώσεις τιμή στην stack πριν καλέσεις την find_Solution. Αυτό δείχνει και ένα πρόβλημα στη σχεδίαση της κλάσης Problem, ασχέτως γλώσσας. H find_Solution χρησιμοποιεί μία εξωτερική σε αυτή μεταβλητή την οποία δεν μπορεί να ξέρει αν έχει τιμή ή όχι. Μπορεί κάποιο άλλο κομμάτι κώδικα να πάει και να βάλει ένα null στο stack με αποτέλεσμα να σκάσει η find_solution χωρίς να καταλάβει το γιατί. Είναι πολύ καλύτερο να περνάς την stack ως παράμετρο στην find_Solution παρά να την έχεις σαν πεδίο.


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  16-01-2008, 14:15 39242 σε απάντηση της 39238

    Απ: Stack

    Κατάλαβα, ευχαριστώ πολύ! Απέφυγα να βάλω τον κώδικα γιατί ήταν αρκετός, την επόμενη φορά θα το κάνω!
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems