1. 程式人生 > 其它 >c# 委託和 lambda

c# 委託和 lambda

一、委託

委託定義指定特定方法簽名的型別。 可將滿足此簽名的方法(靜態或例項)分配給該型別的變數,然後(使用適當引數)直接呼叫該方法,或將其作為引數本身傳遞給另一方法再進行呼叫。 以下示例演示了委託的用法。

using System;
using System.Linq;

public class Program
{
    public delegate string Reverse(string s);

    static string ReverseString(string s)
    {
        return new string(s.Reverse().ToArray());
    }

    
static void Main(string[] args) { Reverse rev = ReverseString; Console.WriteLine(rev("a string")); } }
    • public delegate string Reverse(string s); 行建立特定簽名的委託型別,在本例中即接受字串引數並返回字串引數的方法。
    • static string ReverseString(string s) 方法與定義的委託型別具有完全相同的簽名,用於實現委託。
    • Reverse rev = ReverseString;
       行顯示可將方法分配給相應委託型別的變數。
    • Console.WriteLine(rev("a string")); 行演示如何使用委託型別的變數來呼叫委託
  • 為簡化開發過程,.NET 包含一組委託型別,程式設計師可重用這些型別而無需建立新型別。 這些型別是 Func<>Action<> 和 Predicate<>,可以使用它們而無需定義新的委託型別。 這三種類型之間有一些區別,與它們的預期使用方式有關:

    • Action<> 用於需要使用委託引數執行操作的情況。 它所封裝的方法不返回值。
    • Func<> 通常用於現有轉換的情況,也就是說需要將委託引數轉換為其他結果時。 投影是一個很好的示例。 它所封裝的方法返回指定值。
    • Predicate<> 用於需要確定引數是否滿足委託條件的情況。 它也可以編寫為 Func<T, bool>,這意味著方法返回布林值。
using System;
using System.Linq;

public class Program
{
    static string ReverseString(string s)
    {
        return new string(s.Reverse().ToArray());
    }

    static void Main(string[] args)
    {
        Func<string, string> rev = ReverseString;

        Console.WriteLine(rev("a string"));
    }
}

匿名委託

對於此簡單示例而言,在 Main 方法之外定義方法似乎有些多餘。 .NET Framework 2.0 引入了匿名委託的概念,使你可以建立“內聯”委託,而無需指定任何其他型別或方法。

在下面的示例中,匿名委託將列表篩選為只包含偶數,然後將它們列印到控制檯。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        List<int> list = new List<int>();

        for (int i = 1; i <= 100; i++)
        {
            list.Add(i);
        }

        List<int> result = list.FindAll(
          delegate (int no)
          {
              return (no % 2 == 0);
          }
        );

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}

三、lambda 表示式

但是,即使使用此方法,仍有許多可以丟棄的程式碼。 此時就需要使用 lambda 表示式。 lambda 表示式(或簡稱“lambda”)在 C# 3.0 中作為語言整合查詢 (LINQ) 的核心構建基塊被引入。 這種表示式只是使用委託的更方便的語法。 它們將宣告簽名和方法正文,但在分配到委託之前沒有自己的正式標識。 與委託不同,可將其作為事件註冊的右側內容或在各種 LINQ 子句和方法中直接分配。

由於 lambda 表示式只是指定委託的另一種方式,因此應可重新編寫上述示例,令其使用 lambda 表示式而不是匿名委託。

 

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        List<int> list = new List<int>();

        for (int i = 1; i <= 100; i++)
        {
            list.Add(i);
        }

        List<int> result = list.FindAll(i => i % 2 == 0);

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}

再次強調,lambda 只是委託,這意味著可將其順利用作事件處理程式,如以下程式碼片段所示。

public MainWindow()
{
    InitializeComponent();

    Loaded += (o, e) =>
    {
        this.Title = "Loaded";
    };
}

此上下文中的 += 運算子用於訂閱事件。 有關詳細資訊,請參閱如何訂閱和取消訂閱事件