关闭

匿名方法

389人阅读 评论(0) 收藏 举报
    在原来的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 = delegate{ Console.WriteLine("hello KiddLee"); };
}
delegate void MyDelegate(int i);
    注意:不指定参数列表和参数列表为空是不一样的,如下
    //不指定参数列表,对于MyDelegate来说这种情况是正确的
    MyDelegate MyDele = delegate{ Console.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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:108599次
    • 积分:2000
    • 等级:
    • 排名:第19365名
    • 原创:68篇
    • 转载:76篇
    • 译文:0篇
    • 评论:2条
    文章分类
    文章存档
    最新评论