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

 

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

Client Object Model Context χρησιμοποιει Lambda Εxpression αντι Field Names ?

Îåêßíçóå áðü ôï ìÝëïò Underwater. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 22-08-2011, 16:50. Υπάρχουν 4 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  22-08-2011, 14:05 66872

    Client Object Model Context χρησιμοποιει Lambda Εxpression αντι Field Names ?

    Παρατήρησα ότι από τότε που εμφανίστηκαν τα Lambda Expressions χρησιμοποιώντας παντού (ακόμα και όταν κάνουν το κώδικα ποιο unreadable).

    Για παράδειγμα όταν διαβάζουμε από το SP 2010 χρησιμοποιώντας το Client Object Model, τα Code Samples δείχνου ότι περνάμε στο Context.Load ένα Lambda Expression, αντί το όνομα του field.

    Ξέρει κανείς εάν υπάρχει κάποιο advantage να περάσουμε  «w => w.Title» αντί μόνο «Title».  δηλαδη γιατι στο Method Call ClientContext.Load(object, params retievals) τα parameters "params retrievasl" Πρεπει να ειναι Lambda Expressions και οχι ενα απλο .net Type)

     

     


    “Don’t worry if it doesn’t work right. If everything did, you’d be out of a job.”
    (Mosher’s Law)
  •  22-08-2011, 14:32 66873 σε απάντηση της 66872

    Απ: Client Object Model Context χρησιμοποιει Lambda Εxpression αντι Field Names ?

    Καταρχήν, η εικόνα δεν φαίνεται, αλλά δεν πειράζει. Μάλλον ρωτάς για ένα από δύο πράγματα: ΄

    • Ή δεν καταλαβαίνεις τη διαφορά μεταξύ των δύο μορφών
    • Ή έχεις δει σε πολλά σημεία να περνάνε το lambda αντί για το όνομα ενός πεδίου, property ή method (π.χ. NotifyPropertyChange(()=>MyPropertyName) αντί για NotifyPropertyChange("MyPropertyName") )

    Στην πρώτη περίπτωση, τα statement w=>w.Title και Title είναι εντελώς διαφορετικά. Το ένα είναι ένα function ενώ το δεύτερο ανακτά την τιμή της μεταβλητής του πεδίου Title που βρίσκεται στο scope εκείνη τη στιγμή.

    Όταν περνάς w=>w.Title περνάς ένα function το οποίο θα εκτελεστεί τη στιγμή που θέλει η κλάση ή το function που το δέχεται, με παράμετρο w που θα δώσει η ίδια η κλάση ή το function. Όταν δίνεις το όνομα ενός πεδίου απευθείας (θεωρώντας ότι αυτό το πεδίο υπάρχει στον κώδικα σου) περνάς την τιμή του πεδίου εκείνη τη στιγμή.

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

    Αν η ερώτηση τώρα είναι "γιατί να περάσω lambda αντί για το όνομα του πεδίου με type-safe τρόπο" (χωρίς string φυσικά), η απάντηση είναι ότι το lambda είναι ΠΟΛΥ πιο ευέλικτο. Με το lambda μπορείς άνετα να περάσεις ένα πεδίο ή ένα statement (π.χ. συνδυασμό, trimming, uppercase).

    Στην δεύτερη περίπτωση, το πλεονέκτημα είναι ότι o compiler  ο ίδιος καταλαβαίνει πότε αλλάζει το όνομα ενός property και βγάζει error αν δώσεις κάποιο λάθος όνομα. Επιπλέον, αν χρησιμοποιήσεις κάποιο rename refactoring για να αλλάξεις το όνομα του property, θα αλλάξει το όνομα σε όλα τα lambda. Αν ήταν ένα string ούτε ο compiler ούτε το εργαλείο refactoring θα το εύρισκε.

     


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  22-08-2011, 15:28 66875 σε απάντηση της 66873

    Απ: Client Object Model Context χρησιμοποιει Lambda Εxpression αντι Field Names ?

    Παναγιώτης Καναβός:
    ..ούτε το εργαλείο refactoring θα το εύρισκε.

    Εκτός κι εάν είναι Resharper 6.0 όπου κάτω απο συγκεκριμένες συνθήκες το βρίσκει και το αλλάζει (στο προτείνει κιόλας αμα θες να ψάξει), αλλα κατα βάση αυτό που λέει ο Παναγιώτης είναι το σωστό.. Lambda, always better.


    Παναγιώτης Κεφαλίδης

    "Για να επιτύχεις, θα πρέπει το πάθος σου για την επιτυχία να είναι μεγαλύτερο απο τον φόβο σου για την αποτυχία"

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Παρακαλώ διαβάστε τους όρους χρήσης.
  •  22-08-2011, 15:30 66876 σε απάντηση της 66873

    Απ: Client Object Model Context χρησιμοποιει Lambda Εxpression αντι Field Names ?

    το Code Snippet ειναι

    1
    2
    3
    4
    5
    6
    7
    8
     
    var siteUrl = "http://localhost";
    var context = new ClientContext(siteUrl);
    var web = context.Web
    
    context.Load (web, w => w.Title, w => w.Description);
    
    context.ExecuteQuery();
    Console.WriteLine(web.Title);

    στη γραμμή 5 θα δεις ότι αυτό που θέλουμε είναι απλά να ορίσουμε ποια πεδία (SharePoint List Fields) να κάνουμε retrieve.  Μου φαινεται οιτ θα μπορούσαμε με "ποιο απλό" type-safe τρόπο να ορίσουμε τα πεδία...δεν ειναι? 


    “Don’t worry if it doesn’t work right. If everything did, you’d be out of a job.”
    (Mosher’s Law)
  •  22-08-2011, 16:50 66878 σε απάντηση της 66876

    Απ: Client Object Model Context χρησιμοποιει Lambda Εxpression αντι Field Names ?

    Κάθε προσθήκη στη γλώσσα έχει το δικό της κόστος (περιπλοκότητα, "ρύπανση", ταχύτητα). Προφανώς ο Hejlsberg και η ομάδα του θεώρησαν ότι το κόστος της προσθήκης π.χ. του Title.Property ή Description.Member θα είχε σχετικά περιορισμένη χρήση ενώ μπορούσε να καλυφθεί από άλλες μεθόδους.

    Τέτοια σύνταξη υπάρχει σε αρκετές δυναμικές γλώσσες, και στην ουσία εκτελούν ένα function που σου επιστρέφει την πληροφορία που θέλεις. Εκεί όμως αυτή η δυνατότητα υπάρχει εξαρχής και χρησιμοποιεί μία υποδομή που επιτρέπει και επιταχύνει αυτό τον τρόπο κλήσης. Στην περίπτωση της C# όμως, θα έπρεπε ο compiler να "μαντέψει" ουσιαστικά σε ποιά περίπτωση θέλεις να καλέσεις ένα property και σε ποιά να το περάσεις ως member. Επιπλέον, ο compiler θα έπρεπε να αποφύγει τη δημιουργία κώδικα για reflection γιατί είναι πολύ πιο αργό.

    Με το lambda μπορώ να πάρω πληροφορίες για το property που έδωσα χωρίς να χρησιμοποιήσω reflection. Στην C#, ένα lambda μπορείς άνετα να το δεις ως Expression χωρίς να το εκτελέσεις και να δεις από τί αποτελείται. Για παράδειγμα, το signature της Load δέχεται Expression<Func<T,Object>>. Χωρίς να κοιτάξω τον κώδικα της με το Reflector ή κάτι παρόμοιο, βλέπω ότι μπορώ να φτιάξω την παρακάτω μέθοδο:

     
            private void MyLoad<TRoot>(TRoot root, Expression<Func<TRoot, object>> expression)
            {
                var member = ((expression.Body as LambdaExpression).Body as MemberExpression).Member;
                var memberName = member.Name;
                var myFunction = expression.Compile();
                var value=myFunction(root);            
            }

    Όπως βλέπεις, από την παραπάνω σύνταξη μπορώ να πάρω τόσο το ίδιο το property (member), όσο και ένα function (myFunction) το οποίο θα καλέσει το property επάνω σε όποιο αντικείμενο του περάσω. Όταν έρθει η ώρα μπορώ να καλέσω αυτό το function. Στην πραγματικότητα, σε κανένα σημείο δεν έχω χρησιμοποιήσει Reflection, ούτε καν όταν βρίσκω το όνομα του Property γιατί αυτές οι κλάσεις δημιουργήθηκαν όταν έγινε compile το lambda. Εγώ απλά έκανα τα casts για να πάρω την πληροφορία που ήθελα στο τέλος.

    Προφανώς, έχει μεγάλη σημασία το τί θέλει να κάνει το function. Για παράδειγμα, η MyLoad μου επιτρέπει και να βρω το όνομα του property αλλά και να εκτελέσω το lambda δίνοντας όποιο root αντικείμενο θέλω. Η NotifyPropertyChange που είχα δείξει νωρίτερα από την άλλη, δουλεύει μόνο με τα properties του αντικειμένου στο οποίο έχει οριστεί:

     public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) 
    {
         RaisePropertyChanged(property.GetMemberInfo().Name);
    }

    Και το καλώ ως NotifyOfPropertyChange (()=>MyProperty).

    Τέλος, χωρίς να αλλάξω τον τρόπο κλήσης μπορώ να αλλάξω το τί κανεί το function αλλάζοντας το signature από Expression<Func<T>> σε Func<T>. Σε ένα τέτοιο function μπορώ να καλέσω απευθείας το function ή να το κρατήσω για αργότερα, αλλά δεν θα μπορούσα να βρω το όνομα του. Παρόλα αυτά, η σύνταξη παραμένει η ίδια, π.χ. GetTheValueLater(()=>MyProperty).

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

     


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems