Τα Relaxed Delegates, εύκολα κι απλά…


Τα Relaxed Delegates είναι ένα νέο feature της VB 9 και αν αρέσουν τόσο πολύ στον Don Box, τότε μάλλον αξίζει να τα δούμε λίγο παραπάνω.

Ας αρχίσουμε από ένα VB 8 σενάριο ώστε να φανεί καλύτερα που χρησιμεύουν. Στο .NET Framework 2.0 εμφανίστηκαν τα generics που μας έδωσαν τη δυνατότητα να κάνουμε κάτι σαν το παρακάτω:

    Dim count As Integer
    Dim process As New Action(Of Customer)(AddressOf ProcessElement)

    Sub ProcessElement(ByVal element As Customer)
        count = count + 1
        Console.WriteLine("{0}: {1}", count, element)
    End Sub

    Sub Main()
        Dim list() As Customer = Customer.CreateCustomers
        count = 0
        Array.ForEach(Of Customer)(list, process)
 
        Console.ReadLine()
    End Sub

Το Array.ForEach method παίρνει ως όρισμα ένα array (duh!) και ένα delegate τύπου Action(Of T). Αυτό που κάνει είναι να περνάει ένα προς ένα κάθε item του Array στο delegate (ουσιαστικά στη μέθοδο ProcessElement), δηλαδή χρησιμοποιούμε αυτό αντί να γράφουμε loops.

Αυτό που πρέπει να παρατηρήσετε είναι ότι παντού (στο delegate function, στο delegate declaration αλλά και στο ForEach) χρειάζεται να ορίσουμε τον τύπο των περιεχομένων του Array. Για να φανεί αυτό έγραψα την εκτεταμένη μορφή του κώδικα. Η πιο compact (αλλά ισοδύναμη) είναι η παρακάτω:

    Dim count As Integer
 
    Sub ProcessElement(ByVal element As Customer)
        count = count + 1
        Console.WriteLine("{0}: {1}", count, element)
    End Sub

    Sub Main()
        Dim list() As Customer = Customer.CreateCustomers
        count = 0
        Array.ForEach(list, AddressOf ProcessElement)
Console.ReadLine() End Sub

Είναι προφανές από τα παραπάνω ότι σε περίπτωση που πέρα από objects τύπου Customer είχαμε και objects τύπου Order, τότε θα έπρεπε να φτιάξουμε την αντίστοιχη ProcessElement που να έχει όρισμα ένα Order object. Τα relaxed delegates της VB 9 come to the rescue! Στη VB 9 είναι απόλυτα σωστό το παρακάτω:

    Dim count As Integer

    Sub ProcessElement(ByVal element As Object)
        count = count + 1
        Console.WriteLine("{0} - {1}", count, element)
    End Sub

    Sub Main()
        Dim list() As Customer = Customer.CreateCustomers
        count = 0
        Array.ForEach(list, AddressOf ProcessElement)
        Console.WriteLine("{0} elements were processed.", count)

        Console.ReadLine()
    End Sub

Το list μπορεί να περιέχει οτιδήποτε μέσα, θα εξυπηρετηθεί όμως όπως και να έχει από την ProcessElement. Για την ακρίβεια η ProcessElement μπορεί να μην παίρνει ούτε καν παράμετρο! Ουσιαστικά η VB κάνει πλέον implicit conversion και στα delegates [:)]

Μια πιο απλή και πρακτική εφαρμογή των παραπάνω είναι το εξής σενάριο: Μέχρι και τη VB 8, αν ήθελα αντιστοιχήσω τον ίδιο κώδικα σε δύο διαφορετικά events (πχ KeyDown και MouseDow) θα έπρεπε να έφτιαχνα δύο handlers καθώς η KeyDown έχει ως δεύτερο όρισμα το e τύπου KeyEventArgs ενώ στη MouseDown το e είναι τύπου MouseEventArgs. Τώρα μπορώ απλά να πω:

    Private Sub JustDown() Handles Button1.KeyDown, Button1.MouseDown

    End Sub

Cheers!

Advertisements


Σχολιάστε

Εισάγετε τα παρακάτω στοιχεία ή επιλέξτε ένα εικονίδιο για να συνδεθείτε:

Λογότυπο WordPress.com

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό WordPress.com. Αποσύνδεση / Αλλαγή )

Φωτογραφία Twitter

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Twitter. Αποσύνδεση / Αλλαγή )

Φωτογραφία Facebook

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Facebook. Αποσύνδεση / Αλλαγή )

Φωτογραφία Google+

Σχολιάζετε χρησιμοποιώντας τον λογαριασμό Google+. Αποσύνδεση / Αλλαγή )

Σύνδεση με %s