• 匿名方法


    与前面的可空类型是一样的,匿名方法也是C# 2.0里面提出来的。

    1 匿名方法

       1.1 什么是匿名方法?

            顾名思义,就是没有名称的方法,因为没有名称,匿名方法只能在函数定义(匿名方法是把方法的实现和定义嵌套在了一起)的时候被调用,在其他任何情况下都不能被调用。对于编译器来说,匿名方法并不是没有名字的,编译器在编译匿名方法时会为其生成一个方法名,下面可以通过IL代码来证明。

       

     1 namespace 匿名方法
     2 {
     3     class Program
     4     {
     5         private delegate void VoteDelegate(string name);
     6         static void Main(string[] args)
     7         {
     8             //使用匿名方法来实例化委托对象
     9             VoteDelegate voteDelegate = delegate(string name)
    10             {
    11                 Console.WriteLine("昵称为:{0} 来帮我提高啦",name);
    12             };
    13             //通过调用委托来回调Vote方法,这是隐式调用方式
    14             voteDelegate("Hong");
    15             Console.ReadKey();
    16         }
    17     }
    18 }

        从以上的代码可以看出,委托对象可用匿名方法来实例化的。当并不能一概而论,匿名方法也有它本身的缺点——不能在其他地方被调用,即不具有复用性。而且,匿名方法会自动形成“闭包”。当一个函数(这里成为外部函数)包含对另一个函数(内部函数)的调用时,或当内部函数使用了外部函数的变量时,都会形成闭包。闭包可能会延长外部变量的生命周期。所以如果委托包装的方法相对简单,并且该方法在其他地方的调用频率较低,你就可以考虑用匿名方法来实例化委托对象。

        

        1.2 对变量捕捉过程的剖析

             变量被匿名方法捕获后,变量的生命周期会被延长,就是说对于一个被捕获的变量而言,只要还有任何委托实例在引用它,它就一直存在,就不会在部分委托实例调用结束后被垃圾回收释放掉。下面通过代码来解释:

     1 class Program
     2     {
     3         private delegate void ClosureDelegate();
     4         static void Main(string[] args)
     5         {
     6             ClosureDelegate test = CreateDelegateInstance();
     7             test();
     8             Console.ReadKey();
     9         }
    10 
    11         private static ClosureDelegate CreateDelegateInstance()
    12         {
    13             //外部变量
    14             int count = 1;
    15             ClosureDelegate closureDelegate = delegate()
    16             {
    17                 Console.WriteLine(count);
    18                 count++;
    19             };
    20             closureDelegate();
    21             return closureDelegate;
    22         }
    23     }

    结果:

        我并不知道大家对这个结果是否感到惊讶,第一次输出1是正常的,但第二个输出2确实比较奇妙的。大家可能会认为应该抛出异常才对,因为count在栈上的生命周期已经结束。但结果确实是输出2,是不会错的,我们可以倒推原因,使用匿名方法时,编译器会创建一个额外的类来容纳变量,此时count变量会被分配到堆上的。CreateDelegateInstance方法有该类的一个实例引用,所以此时匿名方法捕捉到的是变量count的一个引用,而不是真真的值。在这个过程中,匿名方法延长了变量count的生命周期。

        对于匿名方法捕捉到的变量,编译器会额外创建一个类来容纳它们。

        

        由上图可知,我们并没有在源码中定义<>c_DisplayClass2_0类。这个类就是编译器创建来容纳捕获的变量count的,该类还容纳了CreateDelegateInstance的方法。

  • 相关阅读:
    第二周学习总结
    调查问卷
    第五周学习总结
    基于DevExpress的项目窗体统一换肤
    一个Linq to Sql 的关联小问题,搞死人
    VC中类型转换(转载)
    保证一个程序只运行一次
    给所有的Control添加发送键盘事件Tab事件,实现回车键自动跳转到下一个控件[基于Shark Xu]
    遍历进程
    CSS Friendly ASP.NET 2.0 Control Adapters (Beta 2.0)在处理URL时的一个Bug
  • 原文地址:https://www.cnblogs.com/Helius/p/5751435.html
Copyright © 2020-2023  润新知