在 2.0 之前的 C# 版本中,聲明委托的唯一方法是使用命名方法。C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表達式取代了匿名方法,作為編寫內聯代碼的首選方式。不過,本主題中有關匿名方法的信息同樣也適用于 Lambda 表達式。有一種情況下,匿名方法提供了 Lambda 表達式中所沒有的功能。匿名方法使您能夠省略參數列表,這意味著可以將匿名方法轉換為帶有各種簽名的委托。這對于 Lambda 表達式來說是不可能的。
要將代碼塊傳遞為委托參數,創(chuàng)建匿名方法則是唯一的方法。這里是兩個示例:
例1:
在Form上拖放一個Button按鈕
書寫相關代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//創(chuàng)建click事件的處理。+=合并委托。將代碼塊傳遞為委托參數
button1.Click += delegate(System.Object o, System.EventArgs e2)
{
System.Windows.Forms.MessageBox.Show("你好,委托!");
};
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("委托示例");
}
}
}
運行結果,先顯示“委托示例”,再顯示“你好,委托”
例2:
//聲明委托
delegate void Printer(string s);
//中間代碼略,完整代碼看最后示例
//利用匿名方法,實例化一個委托
Printer p2=delegate(string s)
{
Console.WriteLine(s);
};
p2("我是中國人,我愛編程。(使用匿名方法)");
備注
匿名方法的參數的范圍是“匿名方法塊”。
如果目標在塊外部,那么,在匿名方法塊內使用跳轉語句(如 goto、break 或 continue)是錯誤的。如果目標在塊內部,在匿名方法塊外部使用跳轉語句(如 goto、break 或 continue)也是錯誤的。
如果局部變量和參數的范圍包含匿名方法聲明,則該局部變量和參數稱為該匿名方法的“外部”變量。例如,下面代碼段中的 age 即是一個外部變量:
例:
delegate void Del();
//中間代碼略,完整代碼看最后示例
//利用該匿名方法的“外部”變量n
int age = 20;
Del p3 = delegate()
{
Console.WriteLine("年齡:{0}", age);
};
p3();
輸出:年齡:20
與局部變量不同,捕獲變量的生命周期一直持續(xù)到引用該匿名方法的委托符合垃圾回收的條件為止。對 age 的引用是在創(chuàng)建該委托時捕獲的。
匿名方法不能訪問外部范圍的 ref 或 out 參數。
在“匿名方法塊”中不能訪問任何不安全代碼。
在 is 運算符的左側不允許使用匿名方法。
示例
下面的示例演示實例化委托的兩種方法:
• 使委托與命名方法 (DoWork) 關聯。
• 使委托與匿名方法關聯。
兩種方法都會在調用委托時顯示一條消息
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MvcUsedKeywords
{
//聲明委托
delegate void Printer(string s);
delegate void Del();
class TestDelegate2
{
static void Main(string[] args)
{
//利用已命名的方法DoWork(),實例化一個委托
Printer p1 = new Printer(TestDelegate2.DoWork);
p1("我是中國人,我愛編程。(使用命名方法)");
//利用匿名方法,實例化一個委托
Printer p2=delegate(string s)
{
Console.WriteLine(s);
};
p2("我是中國人,我愛編程。(使用匿名方法)");
//利用該匿名方法的“外部”變量age
int age = 20;
Del p3 = delegate()
{
Console.WriteLine("年齡:{0}", age);
};
p3();
}
static void DoWork(string s)
{
Console.WriteLine(s);
}
}
}
運行結果:
我是中國人,我愛編程。(使用命名方法)
我是中國人,我愛編程。(使用匿名方法)
年齡:20