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 = 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::'
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
从反编译的结果可以看出:编译后编译器自动生成了一个
.method private hidebysig static void '
{
.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::'
实际上就是执行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::'
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
有红色的部分可以看出,编译后生成了一个
.method private hidebysig static void '
{
.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::'
3、 匿名方法中的外部变量
void Function2()
{
int y = 3;
MyDelegate mydele = delegate
{
Console.WriteLine(y);
};
}
看看Function2生成的反编译代码:
{
// 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'::'
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是编译时生成的类型,而
.method public hidebysig instance void '
{
// 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'::'
由此可以看出匿名方法可以说只是一个委托在C#2.0中的写法,不会带来太多的性能提升
下面谈一下博主的个人看法,匿名方法基本和委托一起使用。