delegate c# - vb.net
DESCRIPTION
ContentsVietnamese ................................................................................................................................................... 2 1. Delegate đại diện cho một Method ...................................................................................................... 2 2. Delegate và Event ................................................................................................................................. 6 2.2 Ta tạo ra một Delegate để xứ lýTRANSCRIPT
Contents Vietnamese ................................................................................................................................................... 2
1. Delegate đại diện cho một Method ...................................................................................................... 2
2. Delegate và Event ................................................................................................................................. 6
2.2 Ta tạo ra một Delegate để xứ lý Event khi mua thêm một xe mới, gồm 2 tham số là đối tượng
tạo ra Event và một tham số mô tả xe máy được mua thêm ............................................................... 6
2.3 Xây dựng class Quản lý xe máy ....................................................................................................... 6
2.4 Cách sử dụng ................................................................................................................................... 8
English ........................................................................................................................................................... 9
Introduction .............................................................................................................................................. 9
Background ............................................................................................................................................. 9
Simple Delegate ....................................................................................................................................... 9
Multicast Delegates ............................................................................................................................... 11
Vietnamese
Sử dụng Delegate trong VB.Net và C#
1. Delegate đại diện cho một Method
Delegate cho chúng ta một cách thuận tiện hơn để thao tác với các method (bao gồm cả hàm và
thủ tục).
Delegate cho phép chúng ta truyền một method như một tham số vào một Method khác ( hay nói
cách khác là delegate đại diện cho một method).
Ví dụ: Ta tạo ra một delegate mô tả một method gồm có 2 tham số kiểu object với giá trị trả về
là kiểu boolean.
Public Delegate Function CompareOp(ByVal object1 As Object, ByVal object2 As
Object) As Boolean
public delegate bool CompareOp(object object1, object object2);
Bây giờ ta tạo ra các method có chữ ký giống với delegate trên (nghĩa là nó có cùng số lượng tham số
(cùng kiểu tham số) và cùng như kiểu trả về).
Các method sau kiểm tra 2 con số là tăng dần hay giảm dần. Ta thấy rằng các Method sau có chữ ký
giống với chữ ký của Delegate.
1. Public Shared Function Sotangdan(ByVal object1 As Object, ByVal object2 As Object) As Boolean
2. If Convert.ToInt32(object1) < Convert.ToInt32(object2) Then
3. Return True 4. Else 5. Return False 6. End If 7. 8. End Function 9. Public Shared Function Sogiamdan(ByVal object1 As Object,
ByVal object2 As Object) As Boolean
10. Return Not Sotangdan(object1, object2)
11. End Function
1. public static bool Sotangdan(object object1, object object2) 2. { 3. if (Convert.ToInt32(object1) < Convert.ToInt32(object2))
4. { 5. return true; 6. } 7. else 8. { 9. return false; 10. }
11.
12. }
13. public static bool Sogiamdan(object object1, object
object2)
14. {
15. return !Sotangdan(object1, object2);
16. }
Method sau là Method BubbleSort nhận tham số đầu vào là một mảng và một method có kiểu giống
Delegate CompareOP. Nó có nhiệm vụ sắp xếp mảng được truyền vào.
1. Public Shared Sub BubbleSort(ByRef Mang() As Object, ByVal compare As CompareOP)
2. Dim temp As Object 3. For i As Integer = 0 To Mang.Length - 2 4. For j As Integer = i + 1 To Mang.Length - 1 5. If compare(Mang(i), Mang(j)) = False Then 6. temp = Mang(i) 7. Mang(i) = Mang(j) 8. Mang(j) = temp 9. End If 10. Next
11.
12. Next
13. End Sub
1. public static void BubbleSort(ref object[] Mang, CompareOP compare)
2. { 3. object temp; 4. for (int i = 0; i <= Mang.Length - 2; i++) { 5. for (int j = i + 1; j <= Mang.Length - 1; j++) { 6. if (compare(Mang(i), Mang(j)) == false) 7. { 8. temp = Mang(i); 9. Mang(i) = Mang(j); 10. Mang(j) = temp;
11. }
12. }
13.
14. }
15. }
Bây giờ ta tạo ra một Class SortClass hoàn chỉnh có nhiệm vụ sắp xếp một mảng số cho trước theo kiểu
tăng dần và giảm dần ứng dụng các Method mới vừa làm ở trên.
1. Public Class SortClass 2. 3. Public Delegate Function CompareOp(ByVal object1 As Object,
ByVal object2 As Object) As Boolean
4. Public Shared Function Sotangdan(ByVal object1 As Object, ByVal object2 As Object) As Boolean
5. If Convert.ToInt32(object1) < Convert.ToInt32(object2) Then
6. Return True 7. Else 8. Return False 9. End If 10.
11. End Function
12. Public Shared Function Sogiamdan(ByVal object1 As
Object, ByVal object2 As Object) As Boolean
13. Return Not Sotangdan(object1, object2)
14. End Function
15.
16.
17. Public Shared Sub BubbleSort(ByRef Mang() As Object,
ByVal compare As CompareOP)
18. Dim temp As Object
19. For i As Integer = 0 To Mang.Length - 2
20. For j As Integer = i + 1 To Mang.Length - 1
21. If compare(Mang(i), Mang(j)) = False Then
22. temp = Mang(i)
23. Mang(i) = Mang(j)
24. Mang(j) = temp
25. End If
26. Next
27.
28. Next
29. End Sub
30. End Class
1. public class SortClass 2. { 3. 4. public delegate bool CompareOp(object object1, object
object2);
5. public static bool Sotangdan(object object1, object object2) 6. { 7. if (Convert.ToInt32(object1) < Convert.ToInt32(object2)) 8. { 9. return true;
10. }
11. else
12. {
13. return false;
14. }
15.
16. }
17. public static bool Sogiamdan(object object1, object
object2)
18. {
19. return !Sotangdan(object1, object2);
20. }
21.
22.
23. public static void BubbleSort(ref object[] Mang,
CompareOP compare)
24. {
25. object temp;
26. for (int i = 0; i <= Mang.Length - 2; i++) {
27. for (int j = i + 1; j <= Mang.Length - 1; j++)
{
28. if (compare(Mang(i), Mang(j)) == false)
29. {
30. temp = Mang(i);
31. Mang(i) = Mang(j);
32. Mang(j) = temp;
33. }
34. }
35.
36. }
37. }
38. }
39.
Cách sử dụng như sau:
1. Private Sub btnSort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSort.Click
2. Dim Number() As Object = {2, 1, 7, 9, 11} 3. SortClass.BubbleSort(Number, AddressOf
SortClass.Sotangdan)
4. SortClass.BubbleSort(Number, AddressOf SortClass.Sogiamdan)
5. End Sub
1. private void btnSort_Click(object sender, System.EventArgs e) 2. { 3. object[] Number = {2, 1, 7, 9, 11}; 4. SortClass.BubbleSort(Number, SortClass.Sotangdan); 5. SortClass.BubbleSort(Number, SortClass.Sogiamdan);
6. }
2. Delegate và Event Delegate ngoài việc dùng cho mục đích ở trên, nó còn dùng cho nhiều mục đích khác ví dụ sử dụng
Delegate để xử lý Event, phần này ta sẽ thảo luận về nó.
Đề bài : Ta tạo một class DanhsachXe quản lý các Xemay mà ta đã mua được
2.1 Đầu tiên ta tạo ra một class mô tả các phần tử xe máy gồm tên xe
và phân khối của xe
1. Public Class XeMay 2. Public Tenxe As String 3. Public Phankhoi As String 4. Public Sub New(ByVal pTenxe As String, ByVal pPhankhoi As
String)
5. Me.Tenxe = pTenxe 6. Me.Phankhoi = pPhankhoi 7. End Sub 8. End Class
1. public class XeMay 2. { 3. public string Tenxe; 4. public string Phankhoi; 5. public XeMay(string pTenxe, string pPhankhoi ) 6. { 7. this.Tenxe = pTenxe; 8. this.Phankhoi = pPhankhoi; 9. } 10. }
2.2 Ta tạo ra một Delegate để xứ lý Event khi mua thêm một xe mới,
gồm 2 tham số là đối tượng tạo ra Event và một tham số mô tả xe máy
được mua thêm
1. Public Delegate Sub XemayHandler(ByVal sender As Object, ByVal e As XeMay)
1. public delegate void XemayHandler(object sender, XeMay e);
2.3 Xây dựng class Quản lý xe máy
1. Public Delegate Sub XemayHandler(ByVal sender As Object, ByVal e As XeMay)
2. Public Class DanhsachXe 3. Public Event AddNewXe As XemayHandler 4. 5. Private Items As New List(Of XeMay)() 6. Public Sub Add(ByVal item As XeMay) 7. Items.Add(item) 8. RaiseEvent AddNewXe(Me, item) 9. End Sub 10. End Class
1. public class DanhsachXe 2. { 3. public event XemayHandler AddNewXe; 4. 5. List<XeMay> Items = new List<XeMay>(); 6. public void Add(XeMay item) 7. { 8. Items.Add(item); 9. AddNewXe(this, item); 10. }
11. }
Các bạn có để ý thấy rằng trong class trên chứa đoạn khai báo event mà sẽ được sinh ra khi ta mua thêm
một chiếc xe máy bằng cách sử dụng Method
1. Public Event AddNewXe As XemayHandler
1. public event XemayHandler AddNewXe;
Đoạn khai báo này nghĩ là Event AddNewXe sẽ được xử lý bởi Delegate XemayHandler
Khi ta dùng method Add thì Event sẽ được sinh ra bằng method sau
Vb.Net
1. RaiseEvent AddNewXe(Me, item)
Hay C#
1. AddNewXe(this, item);
2.4 Cách sử dụng VB.Net
1. Public DS As DanhsachXe 2. ' Khai báo bi?n qu?n lý xe 3. Private Sub Form1_Load(ByVal sender As Object, ByVal e As
EventArgs)
4. DS = New DanhsachXe() 5. AddHandler DS.AddNewXe, AddressOf DS_AddNewXe 6. 'X? lý Event mua xe m?i 7. End Sub 8. 9. 'Ðo?n code x? lý Event Mua xe m?i 10. Private Sub DS_AddNewXe(ByVal sender As Object,
ByVal e As XeMay)
11. MessageBox.Show("Tao m?i mua thêm xe " &
e.Tenxe & " mày th?y ko??")
12. End Sub
13. 'Add thêm xe m?i vào danh sách
14. Private Sub button2_Click(ByVal sender As Object,
ByVal e As EventArgs)
15. DS.Add(New XeMay("Air Blade", "110cc"))
16. End Sub
17.
C#
1. public DanhsachXe DS; // Khai báo biến quản lý xe 2. 3. private void Form1_Load(object sender, EventArgs e) 4. { 5. DS = new DanhsachXe(); 6. //Xử lý Event mua xe mới 7. DS.AddNewXe += new XemayHandler(DS_AddNewXe); 8. } 9. 10. //Đoạn code xủ lý Event Mua xe mới
11. void DS_AddNewXe(object sender, XeMay e)
12. {
13. MessageBox.Show("Tao mới mua thêm xe " +
e.Tenxe + " mày thấy ko??");
14. }
15. //Add thêm xe mới vào danh sách
16. private void button2_Click(object sender, EventArgs
e)
17. {
18. DS.Add(new XeMay("Air Blade", "110cc"));
19.
20. }
21.
English
Introduction
In this article, I've covered a brief introduction about delegates. This can be a good 'Beginner's
Guide' to delegates.
Background
Here, I assume you have a basic knowledge of function pointers. Because, in the introductory
part, I compare delegates with function pointers. For basic ideas on function pointers, please
refer this link.
Simple Delegate
A delegate is very much like a C/C++ 'function pointer' or a 'typedef that represents the address
of a function'. In C/C++, the address of a function is just a memory address. The C/C++ function
pointer holds only the address of a function. This address doesn't carry any additional
information, such as the number of parameters expected by the function, types of parameters it
takes etc. In fact, this all makes a function pointer type unsafe. Traditionally, calling a function
by its address depends on the language supporting the function pointers. And function pointers
are inherently dangerous.
Delegates add a safety to the idea of traditional function pointers. The .NET framework has
added the bonus of providing a type-safe mechanism called delegates. They follow a Trust-But-
Verify model, with automatic verification of the signature by the compiler. Unlike function
pointers however, delegates are object-oriented, type-safe, and secured. In short, a delegate is a
data structure that refers to a static method or to an object instance, and an instance method of
that object. When the delegate references an instance method, it stores not only a reference to the
method entry point, but also a reference to the object instance for which to invoke the method.
In VB.NET, we define a delegate using the 'Delegate' keyword. E.g.:
'Defining the delegate
Public Delegate Sub GreetingDelegate(ByVal MsgString As String)
This does not declare the delegate, it defines it. With this line, we tell the compiler to create a
new class called 'GreetingDelegate' that inherits from 'System.Delegate' (the compiler does it
automatically for you). This line is equivalent to writing the following code in C/C++:
typedef void (*GreetingDelegate) (char *);
This delegate is only capable of calling a method that takes a String parameter and return
nothing. A delegate cares only about the signature of the method you are encapsulating inside of
it. So, the function we encapsulate in this delegate (with the appropriate signature) can be
invoked safely using this delegate.
Here, I have written two different functions in VB.NET:
Public Sub GoodMoring(ByVal YourName As String)
Console.WriteLine("Good Morning " + YourName + " !")
End Sub
Public Sub GoodNight(ByVal YourName As String)
Console.WriteLine("Good Night " + YourName + " !")
End Sub
Now, inside Sub Main, we can create an instance of the delegate, and can assign the address of a
function to the delegate. This is done using the AddressOf keyword as follows:
'Instantiating the delegate
Dim MyGreeting As GreetingDelegate
'Here we assign the address of the function we wish to encapsulate
'to the delegate
Console.WriteLine("Adding 'GoodMoring' Reference To A Delegate...")
MyGreeting = AddressOf GoodMoring
Once we assign an address to a delegate, we can use the Invoke method to call the function
encapsulated in the delegate.
'Invoking the delegate
Console.WriteLine("Invoking Delegate...")
MyGreeting.Invoke("Mallinath")
Because a delegate cares only about the signature of the method you are encapsulating inside it,
we can make it refer to another method also. E.g.:
'Assigning the address of the another function to the same delegate
Console.WriteLine()
Console.WriteLine("Making Existing Delegate To Point To Another Fuction...")
Console.WriteLine("Replacing With Goodnight Reference...")
MyGreeting = New GreetingDelegate(AddressOf Goodnight)
'Another way of invoking the delegate.
Console.WriteLine("Invoking Delegate...")
MyGreeting("Mallinath")
Surprised? Did I forget to put Invoke() there? No! Actually, you don't need to use Invoke(),
you can just use the delegate as a proxy for the method.
If you try to assign the address of a method or function not matching the delegate declaration,
you'll get a compiler error. Try the following code by putting it in the downloaded source code:
'your existing code goes over here
'add these following lines
Public Sub BadGreets()
Console.WriteLine("Wishing You Bad Greetings !")
End Sub
Sub Main()
'your existing code goes over here
'add these following lines and try
MyGreeting = AddressOf BadGreets
MyGreeting.Invoke("Mallinath")
End Sub
Multicast Delegates
Coming to multicast delegates, these are delegates which are capable of pointing to multiple
functions of the same signature. The System.Delegate type maintains a linked list that is used
to hold the references to the functions to be invoked by the delegate. This linked list is called as
the Invocation List. The delegate class provides a shared member function called Combine(),
which adds a reference of specified function to the invocation list.
To demonstrate a multicast delegate, I've added a new function 'GoodEvening', along with the
earlier two, to the MulticastDelegate sample program. And I have created separate delegates for
each one of the earlier functions.
Public Delegate Sub GreetingDelegate(ByVal MsgString As String)
Public Sub GoodMorning(ByVal YourName As String)
Console.WriteLine("Good Morning " + YourName + " !")
End Sub
Public Sub Goodnight(ByVal YourName As String)
Console.WriteLine("Good Night " + YourName + " !")
End Sub
Public Sub GoodEvening(ByVal YourName As String)
Console.WriteLine("Good Evening " + YourName + " !")
End Sub
In Sub Main, I've instantiated them as:
Dim MorningGreets As GreetingDelegate
Dim EveningGreets As GreetingDelegate
MorningGreets = AddressOf GoodMorning
EveningGreets = New GreetingDelegate(AddressOf GoodEvening)
To illustrate the multicast delegate, I've combined both the delegates into a single delegate, using
the Combine() method as:
Console.WriteLine("Adding 'MorningGreets' And" & _
" 'EveningGreets' References To A Delegate...")
Dim AllGreets As GreetingDelegate = _
[Delegate].Combine(MorningGreets, EveningGreets)
Combine() returns a new delegate with the merged invocation list of the function references of
the specified delegates. Here, we can add one more function reference to the existing delegate as:
Console.WriteLine("Adding Another" & _
" References To Existing Delegate...")
AllGreets = [Delegate].Combine(AllGreets, _
New GreetingDelegate(AddressOf Goodnight))
As I wrote, the delegate definition line tells the compiler to create a new class inheriting from the
System.Delegate type:
Dim NightGreets As GreetingDelegate = AddressOf Goodnight
This is equivalent to:
Dim NightGreets As GreetingDelegate
NightGreets = New GreetingDelegate(AddressOf Goodnight)
So, the entire thing can be summed up as:
AllGreets = [Delegate].Combine(AllGreets, _
New GreetingDelegate(AddressOf Goodnight))
As like a function, to add a function reference to a delegate's invocation list, a delegate class
provides a function to remove a function reference from the delegate invocation list.
For example:
Console.WriteLine("Removing 'GoodEvening' Reference...")
AllGreets = [Delegate].Remove(AllGreets, EveningGreets)
An Invoke function call on this multicast delegate will call all the functions whose references
are stored in the invocation list of that delegate object.
Finally, while concluding multicast delegates, I can say that, it differs from a regular delegate in
that it may contain references to more than just one method. Methods in a multicast delegate are
executed synchronously when the multicast delegate is invoked, and in the order in which they
are added to the list. If one of the called method raises an exception, then the delegate ceases,
and the exception is propagated to the delegate caller.