01/10/2018, 17:31

Named methods, Anonymous Methods và Lambda expressions

1. Named method Một delegate có thể sử dụng kết hợp với named method. Khi chúng ta khởi tạo một delegate sử dụng với named method, method có thể truyền như một tham số // Khai báo delegate delegate void Del(int x); // Định nghĩa named method void DoWork(int k) { /* ... */ } // KHởi ...

1. Named method
Một delegate có thể sử dụng kết hợp với named method. Khi chúng ta khởi tạo một delegate sử dụng với named method, method có thể truyền như một tham số

// Khai báo delegate
delegate void Del(int x);

// Định nghĩa named method
void DoWork(int k) { /* ... */ }

// KHởi tạo delegate sử dụng named method như tham số
Del d = obj.DoWork;

Chúng ta có thể sử dụng static method or instanced method để kết hợp delegate, như sau:

// Declare a delegate
delegate void Del();

class SampleClass
{
    public void InstanceMethod()
    {
        System.Console.WriteLine("A message from the instance method.");
    }

    static public void StaticMethod()
    {
        System.Console.WriteLine("A message from the static method.");
    }
}

class TestSampleClass
{
    static void Main()
    {
        SampleClass sc = new SampleClass();

        // Map the delegate to the instance method:
        Del d = sc.InstanceMethod;
        d();

        // Map to the static method:
        d = SampleClass.StaticMethod;
        d();
    }
}

Những thông tin trên có hết trên msdn của Microsoft

Chúng ta xem ví dụ như sau để có thể thấy được sự uyển chuyển của delegate

a. Chúng ta có một lớp Common. Lớp Common chứa một delegate StringFilter giúp chúng ta lọc ra những kiểu string mà chúng ta mong muốn

public class Common
{
  public delegate bool StringFilter(string s);
  public static string[] FilterArrayOfStrings(string[] arr, StringFilter filter)
  {
     ArrayList aList = new ArrayList();
     foreach (string s in arr)
     {
        if (filter(s))
        {
          aList.Add(s);
        }
      }
     return ((string[])aList.ToArray(typeof(string)));
  }
}

b. Chúng ta có một lớp Application để sử dụng lớp Common trên

public class Application
{
  public static bool IsShorterThanFive(string s)
  {
    return s.Length < 5;
  }
}

c. Thực thi ý tưởng

class Program
{
  static void Main(string[] args)
  {
    string[] arr = { "Goc", "Kinh", "Nghiem", "Hoc", "Lap", "Trinh", "LINQ"};
    string[] resullt = Common.FilterArrayOfStrings(arr, Application.IsShorterThanFive);
    foreach (string s in resullt)
      Console.WriteLine(s);
    Console.ReadLine();
 }
}

Như chúng ta thấy trong phần Thực thi ý tưởng, delegate của chúng ta ủy thác cho method IsShorterThanFive làm nhiệm vụ lọc một chuỗi.
Và bạn hãy tưởng tượng xem có một ông lập trình Nguyễn Văn A không thích lọc những chuỗi có chiều dài nhỏ hơn 5, mà ổng thích lọc những chuỗi có chiều dài lớn hơn 8 hoặc những chuỗi chỉ có lower case sẽ như thế nào? Câu trả lời là delegate của chúng ta có đủ sự uyển chuyển để làm điều đó. Và dĩ nhiên ông Nguyễn Văn A sẽ viết các method như IsLongerThanEight, IsLowerCase và ủy thác cho những method đó lọc theo ý ông A muốn.

2. Anonymous method

Như chúng ta đã thấy ở phần trên, chúng ta viết lằng nhằng khá nhiều để sử dụng một delegate như là: khai báo delegate, viết một method cho delegate đó sử dụng…. Anonymous method là cách viết delegate ngắn gọn hơn, từ khóa của nó là inline-code. Chúng ta cải thiện đoạn code trên như sau

string[] arr = { "Goc", "Kinh", "Nghiem", "Hoc", "Lap", "Trinh", "LINQ"};
string[] resullt = Common.FilterArrayOfStrings(arr, delegate(string s) { return s.Length < 5; }); foreach (string s in resullt)
  Console.WriteLine(s);

3. Lambda expression
Lambda expression là một sự cải tiến hơn nữa so với anonymous method. Chúng ta có thể viết code ngắn gọn hơn nữa so với anonymous method Trong C#, toán tử lambda là =>
Nếu chúng ta có một tham số thì cú pháp như sau:
param => expr
Nếu chúng ta có nhiều tham số thì cú pháp như sau:

(param1, param2, …paramN) => expr

Nếu chúng ta có một expression phức tạp, chúng ta phải bỏ nó vào cặp dấu {}

(param1, param2, …paramN) =>
{
  statement1;
  statement2;
  …
  statementN;
  return(lambda_expression_return_type);
}

Có vẻ hơi rối nhỉ? Chúng ta nhìn vào ví dụ sau để hiểu rõ hơn về cú pháp

x => x

Câu lênh trên có nghĩa là input của chúng tôi là x và hãy trả về chúng tôi giá trị x. Bạn hãy tưởng tương lệnh trên tương đương chúng ta viết ra hàm sau:

public int MyFunction(int x)
{
  return x;
}

Hãy cùng xem xét thêm một ví dụ để hiểu rõ hơn:

s => s.Length

Câu lênh trên có nghĩa là input của chúng tôi là chuỗi s và hãy trả về chúng tôi giá trị chiều dài của chuỗi s. Bạn hãy tưởng tương lệnh trên tương đương chúng ta viết ra hàm sau:

public int MyFunction(string s)
{
  return s.Length;
}

Nhìn vào câu lênh sau

(x, y) => x == y

Câu lênh trên có nghĩa là input của chúng tôi là x, y và hãy trả về chúng tôi true hoặc false nếu x bằng y. Bạn hãy tưởng tương lệnh trên tương đương chúng ta viết ra hàm sau:

public bool MyFunction(int x, int y)
{
  return x==y;
}

Và bạn thử xem mình có thể hiểu được câu lênh này không:

(x, y) =>
{
  if (x > y)
    return (x);
  else
    return (y);
}

Cải tiến ví dụ ở phần named method để thấy sự ngắn gọn hơn khi dùng lambda expression:

string[] arr = { "Goc", "Kinh", "Nghiem", "Hoc", "Lap", "Trinh", "LINQ" };
string[] resullt = Common.FilterArrayOfStrings(arr, s => (s.Length < 5));
foreach (string s in resullt)
  Console.WriteLine(s);

0