湖边的白杨树

探索是一种乐趣

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

C#匿名方法和Lambda表达式

当一个调用者想监听传来的事件的时候,它必须定义一个唯一的与相关委托签名匹配的方法。

在事件注册时直接将一个委托与一段代码相关联,这种代码叫做匿名方法。

namespace ConsoleApplication1
{
    class Program
    {
        public class Car
        {
            // 属性
            public string CarName { get; set; }
            public int CurrentSpeed { get; set; }
            public int MaxSpeed { get; set; }

            // 成员
            private bool carIsBroken;

            // 构造函数
            public Car() { MaxSpeed = 180; }
            public Car(string name, int maxSpd, int curSpd)
            {
                CarName = name;
                CurrentSpeed = curSpd;
                MaxSpeed = maxSpd;
               //carIsBroken = false; 
            }

            // 创建一个委托用于对Car事件的响应处理。
            //public delegate void CarEngineHandler(string msg);
            public delegate void CarEngineHandler(object sender, CarEventArgs e); 

            // Car类可以发送的事件
            public event CarEngineHandler eCarIsBroken;
            public event CarEngineHandler eOverSpeedAlarm;

            public void Accelerate(int delta)
            {
                // 如果汽车已坏,触发eCarIsBroken事件
                if (carIsBroken)
                {
                    if (eCarIsBroken != null)    // 触发事件!
                    {
                        //eCarIsBroken("Car is broken,can't drive now!");
                        eCarIsBroken(this,new CarEventArgs("Car is broken,can't drive now!"));
                    }
                }
                else
                {
                    CurrentSpeed += delta;
                }

                // 超速提醒
                if (20 == MaxSpeed - CurrentSpeed && eCarIsBroken != null)  // 触发事件!
                {
                    //eOverSpeedAlarm("Alarm: Going too fast, drive slowly!");
                    eOverSpeedAlarm(this,new CarEventArgs("Alarm: Going too fast, drive slowly!"));
                }

                if (CurrentSpeed >= MaxSpeed)
                {
                    carIsBroken = true;
                }
                else
                {
                    Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);
                }
            }
        }

        // 利用EventArgs的派生类,来传递数据。
        public class CarEventArgs : EventArgs
        {
            public readonly string msg;
            public CarEventArgs(string message)
            {
                msg = message;
            }
        }


        public static void TheCarIsBroken(string msg)
        {
            Console.WriteLine(msg);
        }
       
  
        static void Main(string[] args)
        {
            Car myCar = new Car("Audio Q5", 200, 60); 

            // 采用匿名的方式注册事件处理程序, 匿名方法的最后需要有一个分号结束
            myCar.eOverSpeedAlarm += delegate(object sender, CarEventArgs e)
            {
                Console.WriteLine("{0}:{1}", sender, e.msg);
            };

            myCar.eCarIsBroken += delegate(object sender, CarEventArgs e)
            {
                Console.WriteLine("{0}:{1}", sender, e.msg);
            };


            for (int i = 0; i < 12; i++)
            {
                myCar.Accelerate(20);
            }

            Console.ReadLine();
        }
    }
}

 

Lambda表达式是匿名方法的简单表达方式,从而彻底的简化了对委托的使用。

Lambada表达式是这样编写的:

首先定义一个参数列表,随后加上“=>"标记,然后加上处理这些参数的语句。

Lambda表达式的参数可以使显示类型化,也可以使隐式类型化的。

举例说明如下:利用泛型List<T>的FindAll()方法从一组数据中找出所有的偶数。

方法一:使用传统的委托方法

namespace ConsoleApplication1
{
    class Program
    {
        static void TraditionalDelegate()
        {
            // 创建整数列表
            List<int> myList = new List<int> { };
            myList.AddRange(new int[]{ 1, 2, 3, 4, 5, 9, 10, 21, 30, 68 });

            // 使用传统泛型委托语法调用FindAll
            Predicate<int> callback = new Predicate<int>(IsEvenNumber);
            List<int> evenNumbers = myList.FindAll(callback);

            // 输出结果
            foreach( int evenNumber in evenNumbers)
            {
                Console.WriteLine("{0},",evenNumber);
            }
        }
       
        // Predicate 委托的目标方法
        static bool IsEvenNumber(int number)
        {
            return (0 == number % 2 ? true : false); 
        }

  
        static void Main(string[] args)
        {
            TraditionalDelegate();
            Console.ReadLine();
        }
    }

方法二:使用匿名方法:

// 使用传匿名委托语法调用FindAll
            List<int> evenNumbers = myList.FindAll(
                delegate(int i)
                {
                    return 0 == i % 2; 
                });

方法三:采用Lambda表达式

            // 使用Lambda表达式
            List<int> evenNumbers = myList.FindAll(
          i => 0 == (i % 2) );

 

至此,我们用Lambda表达式来更新之前写的Car 事件

 static void Main(string[] args)
        {
            Car myCar = new Car("Audio Q5", 200, 60);

            // 使用Lambda表达式来挂起事件
            myCar.eOverSpeedAlarm += (sender, e) =>
                {
                    Console.WriteLine(e.msg);
                };
            myCar.eCarIsBroken += (sender, e) =>
                {
                     Console.WriteLine(e.msg);
                };

            for (int i = 0; i < 12; i++)
            {
                myCar.Accelerate(20);
            }

            Console.ReadLine();
        }

 

 总结如下:

1. delegate 关键字间接的构造了一个派生自MuticastDelegate的类,委托对象保存一个方法列表。可以被同步调用(Invoke()),或异步调用(BeginInvoke()和EndInvoke())

2. event 关键字简化了事件发送到调用者的处理过程。

3. 匿名方法可以直接将一段代码与指定事件相关联。Lambda表达式是匿名方法的简化表达方式。

posted on 2013-02-11 15:56  fdyang  阅读(1775)  评论(0编辑  收藏  举报