雁过请留痕...
代码改变世界

Lamda表达式的参数捕获,太酷了

2013-11-28 11:22  xiashengwang  阅读(6402)  评论(1编辑  收藏  举报

lamda表达式有了参数捕获这个功能,让Action这个委托变得无所不能。Action委托就是无参数,无返回值的一个代理类型。

它只能对应于下面这种类型的函数声明。

  public void Function()
        {
            //Do something
        }
  public void Function2()
        {
            //Do something
        }
  public void Function3()
        {
            //Do something
        }

假设我们定义一个共通的执行函数

 public  void Execute(Action action)
        {
            try
            {
                action.Invoke();
            }
            catch (Exception ex)
            {
                //Log
                Debug.WriteLine(ex);
            }
            finally
            { 
            }
        }

那么,调用上面的三个函数,就是这个样子。

Execute(Function);
Execute(Function2);
Execute(Function3);

这么做的好处是,可以将一些共通的处理,例如异常捕获等放到Execute函数里,而其他的被调用函数不用写这部分代码。

但是这样会引申出一个问题,我们的函数不可能都是些无返回值,无参数的函数,例如:

        public bool Edit(Account account)
        {
            bool result = false;
            //Todo
            result = true;
            return result;
        }

那么上面的Excute函数就不适用了,难道我们又要定义一个类似于下面这样的委托吗?

public delegate bool EditDelegate(Account accout);

在项目中往往有很多的函数原型,如何一一这样声明,早就累死了。能不能有一种共通的方式来统一处理所有的函数呢?

Lamda的参数捕获出场了。看看下面这段代码:

            Account account =  new Account();
            AccountService accountService = new AccountService();
            bool result = false;
            Execute(() => { result = accountService.Edit(account); });

我们依然共用了我们先前定义的Exeute函数,但却调用一个有参数,有返回值的函数。这要全归功于Lamda表达式,主要有以下两点:

1,()=>{} 这句Lamda表达式代表了一个无参数,无返回值的委托,也就是和Action委托签名一致,Execute函数也就能调用。

2,这一点最关键,result和account是在Lamda表达式外部定义的变量,被Lamda表达式捕获,作为参数传递和返回值使用。并且,Lamda表达式和外部变量是同步的,也就是Lamda的返回值会改变result的值。这一点当时我也没有想明白,按理说result是bool型,是一个值类型,应该是按值传递的,结果不会被改变。但是Lamda表达式对于所有捕获的外部变量,都是按引用传递的,这一点要谨记!也正是有了这个特点,让我们可以在Lamda表达式的内部利用参数捕获的这个特性来调用任意的函数。而Lamda本身只要和Action委托一致就行了。

我只能说,这个功能真是太酷了。如果你用的好,就可以大大的简化编程。