在 2.0 以前的 C# 版本中,声明委托的惟一方式是使用命名方法。 C# 2.0 引入匿名方法,在 C# 3.0 及更高版本中,Lambda 表达式取代匿名方法做为编写内联代码的首选方式。 可是,本主题中有关匿名方法的信息也适用于 Lambda 表达式。 在有一种状况下,匿名方法提供 Lambda 表达式中没有的功能。 使用匿名方法可省略参数列表。 这意味着匿名方法可转换为具备多种签名的委托。 Lambda 表达式没法实现这一点。 有关 Lambda 表达式的详细信息,请参阅 Lambda 表达式。html
建立匿名方法其实是一种将代码块做为委托参数传递的方式。 这里是两个示例:express
// 为单击事件建立处理程序 button1.Click += delegate(System.Object o, System.EventArgs e) { System.Windows.Forms.MessageBox.Show("Click!"); };
// 建立一个委托. delegate void Del(int x); // 使用匿名方法实例化委托 Del d = delegate(int k) { /* ... */ };
因为使用匿名方法无需建立单独的方法,所以可减小对委托进行实例化的编码开销。编程
例如,在因不得不建立方法而可能出现非必要开销的状况下,指定代码块(而不是委托)颇有用处。 开始新线程就是一个很好的示例。 此类建立一个线程,且还包含该线程执行的代码,而无需为委托建立其余方法。安全
void StartThread() { System.Threading.Thread t1 = new System.Threading.Thread (delegate() { System.Console.Write("Hello, "); System.Console.WriteLine("World!"); }); t1.Start(); }
备注ide
匿名方法的参数范围为匿名方法块。ui
若是目标在匿名方法块以外,匿名方法块内具备 goto、break 或 continue 等跳转语句是一种错误。 若是目标在匿名方法块以内,匿名方法块外具备 goto
、break
或 continue
等跳转语句也是一种错误。编码
范围包含匿名方法声明的本地变量和参数称为此匿名方法的外部变量。 例如,在以下代码段中,n
是一个外部变量:spa
int n = 0; Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };
建立委托时,对外部变量 n
的引用被视为已捕获。 不一样于本地变量,已捕获的变量的生存期一直延伸至引用匿名方法的委托具备垃圾回收资格为止。线程
匿名方法没法访问外部范围的 in、ref 或 out 参数。指针
没法在匿名方法块内访问任何不安全代码。
不容许在 is 运算符左侧使用匿名方法。
以下示例演示实例化委托的两种方式:
将委托与匿名方法相关联。
将委托与命名方法 (DoWork
) 相关联。
在每一种状况下,调用委托时均显示一条消息。
// 定义委托. delegate void Printer(string s); class TestClass { static void Main() { // 使用匿名方法实例化委托类型 Printer p = delegate(string j) { System.Console.WriteLine(j); }; // 匿名委托调用的结果 p("The delegate using the anonymous method is called."); // 使用命名方法“DoWork”的委托实例化 p = DoWork; // 传统方式委托调用的结果 p("The delegate using the named method is called."); } // 与命名委托关联的方法。 static void DoWork(string k) { System.Console.WriteLine(k); } } /* 输出: The delegate using the anonymous method is called. The delegate using the named method is called. */
其余更详细的技术请参考: