匿名委托简化代码
我刚开始没有掌握匿名方法这些就是按照下面这些写的,说实话很痛苦。后来接触了匿名表达式,lambda后几乎都不想再想写这样的东西了,除非特殊的一些情况,比如需要自己定义委托。如果您现在还在按照下面这样写,那么这篇文章对你或许有些帮助!
//声明一个委托
delegate void UpdateProgressDelegate();
//声明一个UpdateProgressDelegate的委托实例
private UpdateProgressDelegate UpdateProgressHandle;
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
//将该委托实例和UpdateProgressValue方法绑定起来
UpdateProgressHandle = new UpdateProgressDelegate(UpdateProgressValue);
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(D));
t.Start();
}
private void D()
{
//其他事情
//..........
progressBar1.Invoke(UpdateProgressHandle); //调用Invoke更新进度条,参数是我们新建的委托
}
//更新进度条的方法
private void UpdateProgressValue()
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
}
这个写法基本就是.net 1.x里面的委托写法了。您也看出来,很繁琐。像一个多线程的界面中,要和多线程打交道的控件何止一个两个。几个一来就会感觉很烦了。维护起来也不方便。 下面我们使用.net 2.0中的一个新特性:支持省略委托的创建,直接将方法名字赋给需要的参数。即我们可以将
Thread t = new Thread(new ThreadStart(D));
改为:
Thread t = new Thread(D);
虽然只是少了一点,不过好歹也是个进步对吧。
现在我们引入.net 2.0中的匿名委托来改善下上面这个程序,使其看起来更加简洁点。怎样使用匿名委托?教你个简单的方法,程序中参数是方法名字的地方您都可以通过delegate(){//操作}的形式来代换。比如下面我们就像D方法名那里给替换掉。
//声明一个委托
delegate void UpdateProgressDelegate();
//声明一个UpdateProgressDelegate的委托实例
private UpdateProgressDelegate UpdateProgressHandle;
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
//将该委托实例和UpdateProgressValue方法绑定起来
UpdateProgressHandle = new UpdateProgressDelegate(UpdateProgressValue);
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(delegate() { progressBar1.Invoke(UpdateProgressHandle); });
t.Start();
}
//更新进度条的方法
private void UpdateProgressValue()
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(delegate() { progressBar1.Invoke(new Action(UpdateProgressValue)); });
t.Start();
}
//更新进度条的方法
private void UpdateProgressValue()
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
}
}
可以看到我们之前声明的那一长段的委托都去掉了,清爽了不少。那么在.net 2中该如何使用呢?两个办法:
1.强制在UpdateProgressValue中加个参数,但我们不使用。代码如下:
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(delegate() { progressBar1.Invoke(new Action<int>(UpdateProgressValue),0); });
t.Start();
}
//更新进度条的方法
private void UpdateProgressValue(int x)
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
}
2.不使用Action委托,还记得我们最朴素写法中的ThreadStart这个委托吗?这个就是一个现成的无参数委托,不用白不用!代码如下:
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(delegate() { progressBar1.Invoke(new ThreadStart(UpdateProgressValue)); });
t.Start();
}
//更新进度条的方法
private void UpdateProgressValue()
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
}
上面我们已经说过了,有方法名为参数的地方可以使用匿名方法替代,那么上面的那个new Action(UpdateProgressValue)中的UpdateProgressValue我们同样可以再给替换掉了。代码如下:
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(delegate()
{
progressBar1.Invoke(new Action(delegate()
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
}));
});
t.Start();
}
我们最后引入lambda来简化我们的代码。Lambda表达式在C#中的写法是“arg-list => expr-body”,“=& gt;”符号左边为表达式的参数列表,右边则是表达式体(body)。参数列表可以包含0到多个参数,参数之间使用逗号分割。当然因为我们这里没有参数所 有可以直接写成()=>{}的形式了啦。lambda用在哪里呢?它可以替换匿名表达式使其更加简单,在LINQ等等查询语句中也有使用,不过不是 我们今天讨论的范围。如何替换匿名表达式呢?代码如下:
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(() => progressBar1.Invoke(new Action(()=>
{
for (int i = 0; i < 50; i++)
{
progressBar1.Value = i;
}
})));
t.Start();
}
可以看到使用了lambda后匿名方法中的一些不需要的{}被省略了,自然看起来也就爽多啦。如果非要总结一个怎么替换的过程的话那就简单的认为将delegate(){}替换为了()=>{},如果有参数类似。