匿名方法——.net2.0新特性

http://www.cnblogs.com/kid-li/archive/2006/12/12/589455.html

在原来的C#版本中我们是这样定义Event:

this.Button1.Click += new EventHandler(Button1_Click)

private void Button1_Click(object sender,EventArgs e)

{

        //…

}

    在现在的2.0版本中有了匿名方法,我们可以将上面的代码这样编写

    this.Button1.Click += delegate{

        //…

}

 

从上面的代码示例可以看出匿名方法的几个要点

1、  匿名方法只存在方法,但没有名字

2、  委托有一种桥接的概念,而匿名方法就是要将这个桥接简化。换句话说:匿名方法允许我们以一种“内联”的方式来编写方法代码,将代码直接与委托实例相关联,从而使得委托实例化的工作更加直观和方便

3、  匿名方法直接与委托实例相关联

 

在匿名方法中,有几点问题要注意:

1、  参数列表,看如下代码:

static void Main(string[] args)

{

     MyDelegate MyDele = delegate(int i) { Console.WriteLine("hello KiddLee"); };

}

delegate void MyDelegate(int i);

    匿名方法可以在delegate关键字后跟一个参数列表(可以不指定),后面的代码块则可以访问这些参数,如果不指定的话也是可以的,如下代码编译时也可以通过。

static void Main(string[] args)

{

     MyDelegate MyDele = delegateConsole.WriteLine("hello KiddLee"); };

}

delegate void MyDelegate(int i);

    注意:不指定参数列表和参数列表为空是不一样的,如下

    //不指定参数列表,对于MyDelegate来说这种情况是正确的

    MyDelegate MyDele = delegateConsole.WriteLine("hello KiddLee"); };

    //参数列表为空,对于MyDelegate来说这种情况是错误的

    MyDelegate MyDele = delegate()Console.WriteLine("hello KiddLee"); };

2、  匿名方法的返回值

如果委托类型的返回值类型为void,匿名方法里不能返回任何值

delegate void MyDelegate();

 

        static void Main(string[] args)

        {

            MyDelegate mydele = delegate

            {

                return;

            };

    }

但是如果委托类型的返回值类型不为void,匿名方法返回值也不能为void

delegate int MyDelegate();

 

        static void Main(string[] args)

        {

            MyDelegate mydele = delegate

            {

                return 100;

            };

    }

3、  外部变量

匿名方法有时会使用一些局部变量和参数,这些局部变量和参数被称为“匿名方法的外部变量”。

外部变量的生存期会由于“匿名方法的捕获效益”而延长,直到委托实例不被引用为止。

public delegate void MyDelegate();

 

        static void Main(string[] args)

        {

            int test = 55;

            Console.WriteLine(test);

            Function(test);

            Console.WriteLine(test);

            Console.Read();

        }

 

        static void Function(int test)

        {

            MyDelegate mydele = delegate

            {

                Console.WriteLine(test);

                test = 11;

                Console.WriteLine(test);

            };

            Console.WriteLine("Before Invoke:" + test);

            mydele.Invoke();

            Console.WriteLine("After Invoke:" + test);

     }

输出结果如下:

55

Before Invoke:55

55

11

After Invoke:11

55

匿名方法的机制:

C#2.0中的匿名方法只是通过编译器简化了委托实例化的工作,不存在性能上的差别。下面来看看以下几点:

1、  静态方法中的匿名方法

delegate void MyDelegate();

static void Function(int test)

        {

            MyDelegate mydele = delegate

            {

                Console.WriteLine("Hello KiddLee");

            };

     }

反编译的结果是:





 

.method private hidebysig static void  Function(int32 test) cil managed

{

  // Code size       34 (0x22)

  .maxstack  3

  .locals init ([0] class ConsoleCSharpStudy1.Program/MyDelegate mydele)

  IL_0000:  nop

  IL_0001:  ldsfld     class ConsoleCSharpStudy1.Program/MyDelegate ConsoleCSharpStudy1.Program::'<>9__CachedAnonymousMethodDelegate1'

  IL_0006:  brtrue.s   IL_001b

  IL_0008:  ldnull

  IL_0009:  ldftn      void ConsoleCSharpStudy1.Program::'<Function>b__0'()

  IL_000f:  newobj     instance void ConsoleCSharpStudy1.Program/MyDelegate::.ctor(object,

                                                                                   native int)

  IL_0014:  stsfld     class ConsoleCSharpStudy1.Program/MyDelegate ConsoleCSharpStudy1.Program::'<>9__CachedAnonymousMethodDelegate1'

  IL_0019:  br.s       IL_001b

  IL_001b:  ldsfld     class ConsoleCSharpStudy1.Program/MyDelegate ConsoleCSharpStudy1.Program::'<>9__CachedAnonymousMethodDelegate1'

  IL_0020:  stloc.0

  IL_0021:  ret

} // end of method Program::Function

    从反编译的结果可以看出:编译后编译器自动生成了一个<Function>b__0'()方法,再来看看这个方法的反编译结果:

.method private hidebysig static void  '<Function>b__0'() cil managed

{

  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )

  // Code size       13 (0xd)

  .maxstack  8

  IL_0000:  nop

  IL_0001:  ldstr      "Hello KiddLee"

  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)

  IL_000b:  nop

  IL_000c:  ret

} // end of method Program::'<Function>b__0'

    实际上就是执行Console.WriteLine("Hello KiddLee")

 

2、  实例方法中的匿名方法

void Function2()

        {

            MyDelegate mydele = delegate

            {

                Console.WriteLine("Hello KiddLee");

            };

     }

再来看看反编译结果:



 



Function2的反编译结果是:

.method private hidebysig instance void  Function2() cil managed

{

  // Code size       34 (0x22)

  .maxstack  3

  .locals init ([0] class ConsoleCSharpStudy1.Program/MyDelegate mydele)

  IL_0000:  nop

  IL_0001:  ldsfld     class ConsoleCSharpStudy1.Program/MyDelegate ConsoleCSharpStudy1.Program::'<>9__CachedAnonymousMethodDelegate3'

  IL_0006:  brtrue.s   IL_001b

  IL_0008:  ldnull

  IL_0009:  ldftn      void ConsoleCSharpStudy1.Program::'<Function2>b__2'()

  IL_000f:  newobj     instance void ConsoleCSharpStudy1.Program/MyDelegate::.ctor(object,

                                                                                   native int)

  IL_0014:  stsfld     class ConsoleCSharpStudy1.Program/MyDelegate ConsoleCSharpStudy1.Program::'<>9__CachedAnonymousMethodDelegate3'

  IL_0019:  br.s       IL_001b

  IL_001b:  ldsfld     class ConsoleCSharpStudy1.Program/MyDelegate ConsoleCSharpStudy1.Program::'<>9__CachedAnonymousMethodDelegate3'

  IL_0020:  stloc.0

  IL_0021:  ret

} // end of method Program::Function2

    有红色的部分可以看出,编译后生成了一个<Function2>b__2'(),再看看此函数的反编译结果:

    .method private hidebysig static void  '<Function2>b__2'() cil managed

{

  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )

  // Code size       13 (0xd)

  .maxstack  8

  IL_0000:  nop

  IL_0001:  ldstr      "Hello KiddLee"

  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)

  IL_000b:  nop

  IL_000c:  ret

} // end of method Program::'<Function2>b__2'

 

3、  匿名方法中的外部变量

void Function2()

        {

            int y = 3;

            MyDelegate mydele = delegate

            {

                Console.WriteLine(y);

            };

     }

    看看Function2生成的反编译代码:





.method private hidebysig instance void  Function2() cil managed

 

{

  // Code size       29 (0x1d)

  .maxstack  3

  .locals init ([0] class ConsoleCSharpStudy1.Program/MyDelegate mydele,

           [1] class ConsoleCSharpStudy1.Program/'<>c__DisplayClass4' '<>8__locals5')

  IL_0000:  newobj     instance void ConsoleCSharpStudy1.Program/'<>c__DisplayClass4'::.ctor()

  IL_0005:  stloc.1

  IL_0006:  nop

  IL_0007:  ldloc.1

  IL_0008:  ldc.i4.3

  IL_0009:  stfld      int32 ConsoleCSharpStudy1.Program/'<>c__DisplayClass4'::y

  IL_000e:  ldloc.1

  IL_000f:  ldftn      instance void ConsoleCSharpStudy1.Program/'<>c__DisplayClass4'::'<Function2>b__3'()

  IL_0015:  newobj     instance void ConsoleCSharpStudy1.Program/MyDelegate::.ctor(object,

                                                                                   native int)

  IL_001a:  stloc.0

  IL_001b:  nop

  IL_001c:  ret

} // end of method Program::Function2

    其中<>c__DisplayClass4是编译时生成的类型,而<Function2>b__3'()是这个类型下的方法,来看看它的反编译代码:

.method public hidebysig instance void  '<Function2>b__3'() cil managed

{

  // Code size       14 (0xe)

  .maxstack  8

  IL_0000:  nop

  IL_0001:  ldarg.0

  IL_0002:  ldfld      int32 ConsoleCSharpStudy1.Program/'<>c__DisplayClass4'::y

  IL_0007:  call       void [mscorlib]System.Console::WriteLine(int32)

  IL_000c:  nop

  IL_000d:  ret

} // end of method '<>c__DisplayClass4'::'<Function2>b__3'

 

由此可以看出匿名方法可以说只是一个委托在C#2.0中的写法,不会带来太多的性能提升



下面谈一下博主的个人看法,匿名方法基本和委托一起使用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值