小新的技术天地

Make It Works !

博客园 首页 新随笔 联系 订阅 管理
在用委托操作方法的时候,往往创建委托的语句离操作方法的代码很远。而匿名方法正好相反,它以“in-line”的方式是委托以及所联系的代码放在了一起。除了这个方便之处,匿名方法还共享了对包含的函数成员的本地状态的存取(anonymous methods have shared access to the local state of the containing function member)。为了使用命名的方法达到共享相同的状态的目的,就需要把本地变量“拎”到手动创建的帮助类(instances of manually authored helper classes)的实例中的field里。

下面这个例子使我们在WinForm程序中最常见到的一个模式:

class InputForm: Form
{
    ListBox listBox;
    TextBox textBox;
    Button addButton;
    
public MyForm() {
        listBox 
= new ListBox();
        textBox 
= new TextBox();
        addButton 
= new Button();
        addButton.Click 
+= new EventHandler(AddClick);
    }

    
void AddClick(object sender, EventArgs e) {
        listBox.Items.Add(textBox.Text);
    }

}


虽然操作方法只有一个语句,但是我们还是要手动创建EventHandler委托,已经包含所有参数的事件处理方法,并且它们是分开的。

而使用匿名方法,我们就可以这样:

class InputForm: Form
{
    ListBox listBox;
    TextBox textBox;
    Button addButton;
    
public MyForm() {
        listBox 
= new ListBox();
        textBox 
= new TextBox();
        addButton 
= new Button();
        addButton.Click 
+= delegate {
            listBox.Items.Add(textBox.Text);
        }
;
    }

}


由于在操作方法内部没有用到参数,我们就没省略了参数列表。如果用到了就需要写上,就像这样:

addButton.Click += delegate(object sender, EventArgs e) {
    MessageBox.Show(((Button)sender).Text);
}
;

在这个例子里,发生了一个隐式转换(从匿名方法转换到EventHandler委托类型-Click事件的类型),这个隐式转换能够成功,也许是因为委托类型的返回类型跟参数列表根匿名方法是兼容的。
关于兼容性的确切规则是这样的:

如果以下某一个成立,委托的参数列表跟匿名方法兼容:
1、匿名方法没有参数列表,委托没有out参数。
2、匿名方法包含的参数列表恰好在数量、类型、修饰符各方面匹配委托的参数。
如果以下某一个成立,委托的返回类型跟匿名方法兼容:
1、委托的返回类型是void,匿名方法没有return语句,或者只有return语句而不带表达式。
2、委托的返回类型不是void,关联于匿名方法的return语句的表达式能够隐式转换为委托的返回类型。
而隐式转换必须满足上面两个都满足才能发生。

再给一个例子:

using System;
delegate double Function(double x);
class Test
{
    
static double[] Apply(double[] a, Function f) {
        
double[] result = new double[a.Length];
        
for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        
return result;
    }

    
static double[] MultiplyAllBy(double[] a, double factor) {
        
return Apply(a, delegate(double x) return x * factor; });
    }

    
static void Main() {
        
double[] a = {0.00.51.0};
        
double[] squares = Apply(a, delegate(double x) return x * x; });
        
double[] doubles = MultiplyAllBy(a, 2.0);
    }

}


其中,Apply方法把一个给定的Function应用于一个double数组a,返回也是一个double数组。在主函数里,Apply的第一个参数是一个匿名方法,这个匿名方法是跟Function委托兼容的。在方法里,我们只是简单的返回double值x的平方。

在MultiplyAllBy方法里,我们为double数组的每一个double值乘上了一个系数,而方法内部,是使用匿名方法达到所需要的操作的。

在生存范围里包含匿名方法的本地变量和参数叫做匿名方法的outer variables。在MultiplyAllBy方法里,a和factor是匿名方法的outer variables,传递给了Apply,由于匿名方法引用了factor,factor就被说成被匿名方法捕获了:)一般来说,本地变量的生存期限制于所关联的block,然而,被捕获的本地变量的生存周期就被延长了,延长到指向匿名方法的委托符合垃圾回收的条件为止。

 

PS:
像我也是刚接触匿名方法,还真有点不习惯,可能表述上会有些问题,还请各位不吝赐教.

posted on 2005-06-07 00:29  小新0574  阅读(1654)  评论(0编辑  收藏  举报