Delegates

27 October 2016

Delegate เป็นประเภทข้อมูลที่ใช้ในการอ้างถึงฟังก์ชันหรือเมธอด บางทีเราเรียก delegate ว่าเป็นพอยน์เตอร์ของฟังก์ชัน ในการใช้ delegate จะทำให้เราสามารถทำงานกับฟังก์ชันได้อย่างปลอดภัย ในภาษา Visual Basic นั้น delegate เป็นประเภทข้อมูลออบเจ็คจากคลาส System.Delegate

ในการใช้งาน delegate เราจะต้องสร้างออบเจ็คของ delegate ขึ้นมาเพื่อให้มันสามารถทำงานได้กับฟังก์ชันหรือเมธอดแบบต่างๆ โดยที่ delegate แต่ละแบบจะทำงานได้กับเฉพาะฟังก์ชันหรือเมธอดที่มีจำนวนพารามิเตอร์เท่ากันเท่านั้น นี่เป็นรูปแบบการประกาศ delegate ในภาษา Visual Basic

Delegate [Sub/Function] DelegateTypeName(parameters)

จากรูปแบบเป็นการประกาศ delegate type โดยจะประกาศได้ภายในคลาสหรือโมดูลเท่านั้น เราใช้คำสั่ง Delegate และกำหนดชื่อและ signature ของฟังก์ชันให้กับ delegate นั่นหมายความว่ามันสามารถนำไปใช้ได้กับฟังก์ชันที่มี signature ที่เหมือนกันเท่านั้น

การใช้งาน Delegate

เพื่อทำให้คุณเข้าใจมากขึ้น ต่อไปมาดูตัวอย่างการประกาศประเภทของ delegate การนำมาสร้าง delegate ออบเจ็ค และการทำงานของ delegate ร่วมกับฟังก์ชัน เราจะสร้าง delegate สำหรับทำงานร่วมกับฟังก์ชันที่มีเพียง 1 พารามิเตอร์

Module DelegateExample

    Delegate Sub GreetingDelegate(ByVal name As String)

    Sub Hello(ByVal name As String)
        Console.WriteLine("Hello " & name)
    End Sub

    Sub Bye(ByVal name As String)
        Console.WriteLine("Bye " & name)
    End Sub

    Sub Main()

        Dim a = New GreetingDelegate(AddressOf Hello)
        a("Mateo")

        a = AddressOf Bye
        a("Mateo")

    End Sub

End Module

ในตัวอย่างเป็นการใช้งาน delegate ในภาษา Visual Basic ที่จะใช้ให้มันทำงานกับฟังก์ชัน

Delegate Sub GreetingDelegate(ByVal name As String)

คำสั่งนี้เป็นการประกาศประเภทของ delegate โดยเราได้ตั้งชื่อว่า GreetingDelegate โดย delegate นี้จะสามารถนำไปใช้งานได้กับฟังก์ชันที่ไม่มีการ return ค่ากลับ (เพราะว่าเราสร้าง delegate จากคำสั่ง Sub) และมีพารามิเตอร์ที่เป็นแบบ String หนึ่งตัว

Dim a = New GreetingDelegate(AddressOf Hello)

ในฟังก์ชัน Main เป็นการนำ delegate มาสร้างออบเจ็คเพื่อใช้งานกับฟังก์ชัน โดยตัวแปร a นั้นเป็นตัวแปรของ delegate ที่สามารถทำงานได้กับฟังก์ชันที่ได้กำหนดไว้ใน delegate type GreetingDelegate เราได้กำหนดให้ a อ้างถึงเมธอด Hello() โดยใส่ที่อยู่ของเมธอดในคอนสตรัคเตอร์ในคำสั่ง AddressOf Hello

a("Mateo")

ในตอนนี้ delegate a ของเราทำงานเหมือนเมธอด Hello() เราสามารถเรียกใช้งานเมธอดได้ดังคำสั่งด้านบน

a = AddressOf Bye
a("Mateo")

ต่อมาเราเปลี่ยนให้ delegate a อ้างถึงเมธอด Bye() และเรียกใช้เมธอดนั้นโดยผ่านตัวแปร delegate เช่นเดิม คุณจะสังเกตุว่าเมธอดทั้งสองสามารถทำงานได้กับ delegate type GreetingDelegate เพราะว่ามันเป็นเมธอดแบบ Sub และมีพารามิเตอร์แบบ String 1 ตัว ดังนั้นถ้าเราต้องการให้มันทำงานกับเมธอดชนิดอื่นเราต้องประกาศ delegate type ขึ้นมาใหม่

Hello Mateo
Bye Mateo

และนี่เป็นผลลัพธ์ของการเรียกใช้เมธอดผ่าน delegate

Multi-casting delegate

Multi-casting delegate คือการที่เราสามารถเพิ่มเมธอดมากกว่าหนึ่งเมธอดเข้าไปยัง delegate เพื่อให้สามารถเรียกใช้เมธอดภายในครั้งเดียวได้ มาดูตัวอย่างการ Multi-casting delegate ในภาษา Visual Basic

Module MulticastingDelegate

    Delegate Sub MathDelegate(ByVal num1 As Integer, ByVal num2 As Integer)

    Sub Add(ByVal num1 As Integer, ByVal num2 As Integer)
        Console.WriteLine("{0} + {1} = {2}", num1, num2, num1 + num2)
    End Sub

    Sub Mul(ByVal num1 As Integer, ByVal num2 As Integer)
        Console.WriteLine("{0} * {1} = {2}", num1, num2, num1 - num2)
    End Sub

    Sub Main()

        Dim a As New MathDelegate(AddressOf Add)
        Dim b As New MathDelegate(AddressOf Mul)

        Dim c As MathDelegate = 
            DirectCast([Delegate].Combine(a, b), MathDelegate)
        c(3, 5)

    End Sub

End Module

ในตัวอย่างเป็นการรวมเมธอดไว้ใน delegate เดียวกัน โดยเรามีเมธอด Add() เป็นเมธอดในการบวกเลขสองตัว และเมธอด Mul() สำหรับในการคูณเลข และเราได้ประกาศ delegate type MathDelegate สำหรับใช้กับเมธอดเหล่านี้ และต่อมาเราได้สร้าง delegate ออบเจ็คสำหรับเมธอดทั้งสองในตัวแปร a และ b ตามปกติ

Dim c As MathDelegate = 
    DirectCast([Delegate].Combine(a, b), MathDelegate)

ในตัวแปร delegate c เป็นการนำเมธอดใน a และ b มารวมกันโดยฟังก์ชัน [Delegate].Combine(a, b) และทำการ casting ให้เป็น delegate type MathDelegate ด้วยฟังก์ชัน DirectCast()

ในตอนนี้ ตัวแปร delegate c นั้นอ้างถึงทั้งสองเมธอด ดังนั้นในการเรียกใช้งานเมธอดในคำสั่ง c(3, 5) จึงทำให้เมธอดทั้งสองทำงานโดยการเรียกเพียงแค่ครั้งเดียว

3 + 5 = 8
3 * 5 = 15

นี่เป็นผลลัพธ์ของโปรแกรมในตัวอย่าง

และคุณสามารถเพิ่มจำนวนของฟังก์ชันได้ตามต้องการจาก overloading ของฟังก์ชัน เช่น Combine(a, b, ...)

Lambda Expressions

Lambda Expressions คือฟังก์ชันที่ไม่มีชื่อที่สามารถสร้างขึ้นมาได้ทันทีและเรียกใช้ได้เหมือนฟังก์ชันทั่วไป ซึ่งในภาษา C# จะเรียกว่า Anonymous methods โดย Lambda Expressions นั้นจะทำให้เราสามารถสร้างฟังก์ชันในตอน run time และกำหนดให้กับ delegate โดยตรง มันมักจะใช้กับการส่งฟังก์ชันสำหรับทำงานใน Thread หรือการจัดการ Event

Module LambdaExpressions

    Sub Main()

        Dim buttonClick = Sub() Console.WriteLine("Button clicked")

        Dim listSelected = Sub(ByVal item As String)
                               Console.WriteLine("Selected " & item)
                           End Sub

        buttonClick()
        listSelected("Visual Basic")

        Console.WriteLine((Function(ByVal x As Integer) x * x)(5))

    End Sub

End Module

ในตัวอย่างเป็นการประกาศ Lambda Expressions ในภาษา Visual Basic ซึ่งมี 2 แบบที่แตกต่างกัน คือ inline และ multi-line

Dim buttonClick = Sub() Console.WriteLine("Button clicked")

Dim listSelected = Sub(ByVal item As String)
                       Console.WriteLine("Selected " & item)
                   End Sub

แบบแรกเป็นแบบ inline โดยจะเขียนเรียงต่อกันในบรรทัดเดียวไม่มีคำสั่ง End Sub เราได้กำหนดฟังก์ชันให้กับตัวแปร buttonClick ดังนั้นมันจะเป็น delegate โดยอัตโนมัติ และแบบที่สองเป็น multi-line Lambda Expressions

Console.WriteLine((Function(ByVal x As Integer) x * x)(5))

ในแบบสุดท้ายก็เป็น inline เช่นเดียวกัน แต่จะมีการส่งค่ากลับด้วย โดยในส่วนของคำสั่งจะแบ่งออกเป็นสองส่วนคือ (Function(ByVal x As Integer) x * x) เป็นการประกาศส่วนการทำงาน และ (5) เป็นการใช้งานโดยการส่งพารามิเตอร์เข้าไปยังฟังก์ชัน และในตอนท้ายฟังก์ชันและส่งค่ากับมาเพื่อแสดงผล

Button clicked
Selected Visual Basic
25

นี่เป็นผลลัพธ์ในการทำงานของโปรแกรมของการใช้งาน Lambda Expressions

ในบทนี้คุณได้เรียนรู้เกี่ยวกับ delegate ในภาษา Visual Basic ซึ่งสามารถทำให้เราเรียกใช้เมธอดได้อย่างปลอดภัย เช่น การทำงานภายใน thread ที่มีการทำงานร่วมกับ GUI นั้นจะต้องใช้ delegate ในการ นอกจากนี้ delegate ยังมักจะใช้ร่วมกับ event ซึ่งคุณจะได้เรียนในบทต่อไป

บทความนี้เป็นประโยชน์หรือไม่?Yes·No