Thứ Tư, 28 tháng 1, 2009

Sử dụng Delegate trong lập trình

Bên cạnh Generic Programming (Template Programming), thì Delegate cũng là một trong advanced technique trong lập trình C#. Lần trước tôi đã giới thiệu mọi người Generic Programming, lần này tôi xin giới thiệu Delegate trong C#, trong Java chưa có kỹ thuật tương tự. Nếu biết tận dụng delegate, việc code sẽ trở nên tổng quát hơn, ngắn gọn hơn, tính tái sử dụng tăng cao, và performance giảm ko đáng kể.
Hiểu một cách đơn giản, Delegate tương tự như con trỏ hàm trong C++, nó là con trỏ hàm bởi nó có thể trỏ vào các hàm khác nhau (nếu các hàm đó có cùng giao diện), và người ta có thể gọi một hàm thông qua con trỏ hàm, bằng cách cho con trỏ hàm trỏ vào hàm đó, và call con trỏ hàm cũng tương đương việc call hàm được con trỏ hàm trỏ đến.

Khai báo delegate, chú ý delegate ngang hàng với khai báo class tương tự enum và struct, hãy khai báo delegate bên ngoài class, ex :

public delegate int Compare(int inA, int inB);

Hoặc tốt nhất là khai báo khai báo dạng template, tăng tính tái sử dụng.

public delegate int Compare<T>(T inA, T inB);
public delegate int Compare<T, E>(T inA, E inB);

public delegate T DFunc0Para<T>();
public delegate T DFunc1Para<E, T>(E x);
public delegate T DFunc2Para<E, F, T>(E x, F y);
public delegate void DProc1Para<E>(E x);
public delegate void DProc2Para<E, F>(E x, F y);

Giao diện một delegate sẽ đại diện cho các hàm mà delegate này có thể trỏ tới, gồm kiểu trả về và danh sách tham số, còn tên delegate hay tên hàm ko quan trọng.

Khai báo một biến có kiểu Delegate :

Compare<string> compare;

Thực hiện trỏ một delegate tới một hàm, ex :

compare = Compare;

Call một hàm thông qua delegate :

compare("heno", "hi");

Ví dụ đơn giản :

// ham dc khai bao de cho delegate tro toi
private int CompareFunc(string x, string y)
{
return x.CompareTo(y);
}
public void testDelegate()
{
// khai bao bien kieu Delegate
Compare<string> compare;

// thuc hien tro bien delegate den ham Compare ben tren,
// giao dien cua ham va Delegate phai tuong thich thi moi tro dc

compare = CompareFunc;

// thuc hien call delegate
int val = compare("heno", "hi");
}

Một số ví dụ sử dụng delegate :
- List.RemoveAll và List.ConvertAll : List là lớp sẵn có của C#, và giao diện của RemoveAll và ConvertAll như sau :

public int RemoveAll(Predicate<T> match);
public delegate bool Predicate<T>(T obj);

public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter);
public delegate TOutput Converter<TInput, TOutput>(TInput input);

Và sau đây là ví dụ đoạn code sử dụng chúng, cho thấy cách sử dụng delegate, ví dụ sau cho thấy là ta có thể truyền một function như là tham số của function khác.

public class Test{
public void testListAndDelegate()
{
List<int> listNo = new List<int> (new int[]{1, 2, 3, 3, 4, 5, 6, 5, 3});

// thuc hien xoa cac element co gia tri 3 trong listNo
// trong do equalThree la mot function dc khai bao ben duoi
listNo.RemoveAll(equalThree);

// thuc hien chuyen listNo thanh mot danh sach List tuong ung
// trong do Convert.ToString la mot function cua C# co
// khai bao "public static string ToString(int no)"

List<string> listStr = listNo.ConvertAll<int, string>(Convert.ToString);
}
private bool equalThree(int no)
{
return (no == 3);
}
}

- Tìm kiếm sử dụng Delegate thay vì sử dụng IComparer :
Đây lại là một ví dụ sử dụng Template Delegate, dc dùng trong hàm LinearSearch, hàm này viết dưới dạng Template, nên có thể thích ứng với rất nhiều input khác nhau

public class CommonFunction{
// ham nay tra ve vi tri cua phan tu thuoc array of type tuong ung voi key of type
// trong do E va K la hai kieu bat ki
// Compare la delegate da dc khai bao ben tren
public static int linearSearch<E, K>(List list, K key, Compare<E, K> compare)
{
for (int i = 0; i < list.Count; i++) {
if (compare(list[i], key) == 0) {
return i;
}
}
return CommonConstant.UNFOUND;
}
}// end of CommonFunction
/////////////

public struct Pair{
public int no;
public string name;
public Pair(int inNo, string inName){
no = inNo;
name = inName;
}
}

public class Test{

// khai nay dc khai bao de su dung nhu la tham so
// cho ham linearSearch ben duoi
private int compareFunc (Pair x, int y)
{
return x.no.CompareTo(y);
}

public void testLinearSearch()
{
List<Pair> list = new List<Pair>();
list.Add(new Pair(1, "Mot"));
list.Add(new Pair(3, "Ba"));
list.Add(new Pair(4, "Bon"));
list.Add(new Pair(2, "Hai"));

// tiep theo, ta muon tim index cua phan tu tuong ung voi "no" = 3,
// ta chi can code nhu sau, compareFunc chinh la ham ben tren
int index = CommonFunction.linearSearch(list, 3, compareFunc);
}

}// end of Test

Không có nhận xét nào:

Đăng nhận xét