【整理】C#2.0特性之匿名方法和迭代器
匿名方法的由来
我们在这里用事件的定义来举例,没有匿名方法的时候
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
addButton.Click +=new EventHandler(addClick);
}
protected void addClick(object sender, EventArgs e)
{
listBox.Items.Add(textBox.Text);
}
}
{
protected void Page_Load(object sender, EventArgs e)
{
addButton.Click +=new EventHandler(addClick);
}
protected void addClick(object sender, EventArgs e)
{
listBox.Items.Add(textBox.Text);
}
}
有了匿名方法以后
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
addButton.Click += delegate {
listBox.Items.Add(textBox.Text);
};
}
}
{
protected void Page_Load(object sender, EventArgs e)
{
addButton.Click += delegate {
listBox.Items.Add(textBox.Text);
};
}
}
匿名方法的简介
1.匿名方法允许我们以一种"内联"的方式编写方法代码,将代码直接与委托实例相关联,从而使得委托实例化的工作变得更加直观和方便
2.匿名方法的几个相关问题
-匿名方法的参数
a.匿名方法可以在delegate关键字后跟一个参数列表(如果方法体没用到参数可以不指定),后面的代码块则可以访问这些参数。
b.参数列表必须与使用匿名方法的委托的参数列表完全相同。
带参数的匿名方法
-匿名方法的返回值
a.如果委托类型的返回值为void,那么匿名方法就不能有返回值
b.如果委托类型的返回值不为void,那么匿名方法的返回值就必须与委托类型的返回值类型一致。
如下示例
delegate void MyDelegate();
MyDelegate g = delegate{
......
return;//也可忽略不写
}
delegate int MyDelegate();
MyDelegate g= delegate{
......
return 100;
}
-外部变量
a.一些局部变量和参数有可能被匿名方法所使用,它们被称为"匿名方法的外部变量"。
b.外部变量的生存期会由于匿名方法"捕获效应"而延长,一直延长到委托实例不被引用为止。
delegate double Function();
static void CustomFunction(double data)
{
Function f = delegate {
data += 0.2;
return data;
};
}
static void CustomFunction(double data)
{
Function f = delegate {
data += 0.2;
return data;
};
}
委托类型的推断
1.C#2.0允许我们在进行委托实例化时,省略掉委托类型,而直接采用方法名,C#编译器会做合理的推断
2.由于C#2.0有了委托类型推断功能,所以2.0针对1.0有如下改变
在1.0中
addButton.Click += new EventHanddler(AddClick);
Apply(a,new Function(Math.Sin));
在2.0中
addButton.Click += AddClick;
Apply(a,Math.Sin);
匿名方法机制
1.C#2.0中的匿名方法仅仅是通过编译器的一层而外处理,来简化委托实例化的工作。它与以前版本不存在根本性的差别。
2.深入了解匿名方法机制
-静态方法中的匿名方法
public delegate void D();
static void F(){
D d = delegate{
Console.WriteLine("test");
}
}
上面的代码将被编译器转换为如下代码
static void F(){
D d = new D(_Method1);
}
static void _Method1(){
Console.WriteLine("test");
}
-实例化方法中的匿名方法
class Test
{
int x;
void F()
{
D d = delegate{Console.WriteLine(this.x);};
}
}
上面的代码被编译器转换为
void F()
{
D d = new D(_Method1);
}
void _Method1()
{
Console.WriteLine(this.x);
}
-匿名方法中的外部变量
void F()
{
int y = 123;
D d = delegate{Console.WriteLine(y)};
}
上面的代码被编译器转换为
class _Temp
{
public int y;
public void _Method1()
{
Console.WriteLine(y);
}
}
void F()
{
_Temp t = new _Temp();
t.y=123;
D d = new D(t._Method1);
}
迭代器
在没有迭代器之前,创建一个可用于foreach的集合,如下做法
2.0以前版本实现可foreach的集合
C#2.0中使用迭代器定义可foreach的集合
用迭代器生成可foreach的集合
用迭代器生成可foreach的集合(含中断迭代)
测试实例
注意上图中含有yield break;语句的测试结果为
4,1