zoukankan      html  css  js  c++  java
  • C#基础—匿名方法(Anonymous Mehod)

    1、引入匿名方法

        早在C# 2.0中就提出了匿名方法,实现了以一种内联的方式声明委托,在此之前,声明委托唯一的方法是"命名方法",虽然 C# 3.0 里有了lambda ,使得写内联代码更加简洁和方法,但是匿名方法依然有他的用处,匿名方法提供了可以忽略参数列表的能力。

    2、匿名方法的使用和注意点

        什么匿名方法?简单的理解就是没有定义名字的方法(其实编译器还是帮我们生成了一个方法)。代码的实现就是把方法的定义和方法的实现内联到了一起。

        先看个演示例子:

     1 class Program
     2 {
     3     static void Main(string[] args)
     4     {
     5         Thread t1 = new Thread(printMethod);
     6         t1.Start();
     7 
     8         Console.Read();
     9     }
    10 
    11     static void printMethod()
    12     {
    13         Console.WriteLine("Start Thread");
    14     }
    15 
    16 }

      如果使用匿名方法,就是把方法定义和方法实现内联到一起,避免重新定义命名方法,看Demo:

     1 class Program
     2 {    
     3         static void Main(string[] args)
     4         {
     5               Thread t1 = new Thread(delegate()
     6                       {
     7                             Console.WriteLine("Thread Start");
     8                       });
     9 
    10                t1.Start();
    11 
    12                Console.Read();
    13        }
    14 }                    

        这是一个简单使用匿名方法内联委托实例的例子,在使用匿名方法时,有一些注意点如下:

       (1)、匿名方法中,外部变量的引用被称为"捕获的外部变量",与本地变量不同,捕获的变量的生存期被扩展或延长,直到引用该匿名方法委托被垃圾回收。

       (2)、匿名方法不能访问外部范围的 ref 或 out 参数。

       (3)、在"匿名方法块"中不能访问任何不安全代码,即不能使用指针。

       (4)、在 is 运算符的左侧不允许使用匿名方法。

        这里,需要特别提下的是,匿名方法中的外部变量问题,在使用匿名方法时会形成闭包(closure),与javascript 中的闭包类似。

        先看下演示的例子:

     1 public delegate void DelegateDemo();
     2 
     3 class Program
     4 {
     5     static void Main(string[] args)
     6     {
     7         DelegateDemo d = TestCaptureVariable();
     8         d(); //再次调用
     9 
    10         Console.Read();
    11     }
    12 
    13     static DelegateDemo TestCaptureVariable()
    14     {
    15         //被捕获的外部变量(就是在匿名方法中引用到的变量)
    16         int captureVariable = 100;
    17         int variable = 101;
    18         DelegateDemo d = delegate()
    19         {
    20             Console.WriteLine(captureVariable);
    21             captureVariable = 200;
    22         };
    23 
    24         d(); //声明完后直接调用
    25         return d;
    26     }
    28 }            

    程序输出:

    100

    200

         在本示例程序中,定义了值类型变量captureVariable ,定义在栈上,当第一次调用d(),并结束执行TestCaptureVariable方法后,captureVariable 和 variable 应该被GC回收了,但我们第一次调用d()时,仍然输出了200。

        这种效果就是第一点所说的"捕获变量"的生存周期会因为引用一直存在而被延长。对此,我们可以看下编译器为此做了些什么:

        在Program类中多了一个系统自动命名的类,DisplayClass1,这个类里,包含了 captureVariable,其实,编译器对captureVariable,这个匿名方法中的"被捕获变量" 做了一个特别的处理,自动生成了一个类,这个类中包含了该变量,而匿名方法一直保留了对这个类的引用,所以没有被GC回收,所以除了栈上,在其他地方也保存了这个变量,从而导致这个变量并没有被销毁,从而达到了"延长生命周期"的目的。

  • 相关阅读:
    INSPIRED启示录 读书笔记
    INSPIRED启示录 读书笔记
    INSPIRED启示录 读书笔记
    INSPIRED启示录 读书笔记
    dialog窗口也能刷新
    js验证数字及操作备份
    工具类
    查询结果设置背景色
    decmain主体类经典保存备份
    jquery操作备份
  • 原文地址:https://www.cnblogs.com/ydchw/p/3735517.html
Copyright © 2011-2022 走看看