using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Xml.Linq; using System.IO; namespace LambdaExpressionStudyNote { /// <summary> /// Lambda Expression 是MS在C#3.0中引入的。Lambda表达式最早可见于LISP语言,美国数学家Alonzo Church在1936年将其概念化,这种表达式为描述算法提供一种简便手段。 /// 通过C#2.0的命名方法到匿名方法然后到Lambda表达式的演变来学习Lambda表达式 /// </summary> public class Program { static void Main(string[] args) { //测试 FilterArrayOfInt(); #region 一、使用命名方法(named Methods) int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int[] filterNumbers = FilterArrayOfInt(numbers, AppliationTest.IsOdd);//委托方法作参数传入时无须托号 Console.WriteLine("使用委托,命名方法来实现过滤后的结果"); foreach (int i in filterNumbers) { Console.WriteLine(i); } //结果1 3 5 7 9,不同的算法实现者,可以写出各种不同的filter,然后代入即可。 #endregion #region 二、使用匿名方法(Anonymous Methods) //在C#2.0中,引入了匿名方法,可以将代码内联来替换委托。上面的示例中Main()方法里,filterNumbers的赋值可以改定如下: Console.WriteLine("使用匿名方法来实现过滤后的结果"); int[] filterNumbers2 = FilterArrayOfInt(numbers, delegate(int i) { return ((i & 1) == 1); }); /* 在委托参数的地方可以简单的用这种内联的形式,由于没有定 * 义一个确定的名称方法,就称作匿名方法,对于不怎么需要重 * 复的代码,这种手段可以极大的简化程序结构,但降低的可读 * 性,对于比较复杂的函数体就很(suck)了 suck ??? */ foreach (int i in filterNumbers2) { Console.WriteLine(i); } #endregion #region 三、使用Lambda 表达式 //使用Lambda 表达式 /*Lambda表达式的一般形式,由一组由逗号分隔的参数列表,跟着一个lambda操作符,再跟着一个表达式或者语句块,多个输入参数的情况需要用括号来包围,在C#中,lambda *操作符是 => ,因此,在C#中的lambda 表达式应该是这样子的: * (param1,param2,...paramN) => * { * statement1; * statement2; * statementN; * return (lambda_expression_return_type); * } */ /* 再回过头看delegate的部分,一个dalegate实际上就是指定输入的参数格式返回值的格式,那么在lambda表达式,就对应着 => 左边的那一块及语句体里return的那些内容,在前 * 面的例子中,输入一个int型数据,返回一个bool变量,比如: x => x.length > 0 ;这个表达式可以读作:“x goes to x.length > 0”,或者“输入x, 返回 x.length > 0 ”. * 下面的lambda 表达式可以返参数的长度: s => s.length; 对于多个变量 比如:(x,y) => x==y; * 再复杂点:(x,y) = > * { if (x>y) * return (x); * else * return (y); * } * 好,下成我们来改造前面例子,算法设计所设计的lambda表达式必须满足委托的声明: * delegate bool IntFilter(int i); 刚可以将filterNumbers2的赋值写成这样: */ int[] filterNumbers3 = FilterArrayOfInt(numbers, i => ((i & 1) == 1)); Console.WriteLine("使用Lambda表达式来实现过滤后的结果"); foreach (int i in filterNumbers3) { Console.WriteLine(i); } #endregion LinqToXmlApplication.ReadXml(); } /// <summary> /// 数组过滤器的委托 /// </summary> /// <param name="i">数</param> /// <returns>过滤结果</returns> public delegate bool intFilter(int i); /// <summary> /// 在引入Lambda表达式之前,先看一下,将一个算法作为一个参数传递给一个方法是如何做到的? /// 一、采用命名方法(Named Methods) /// 在C#2.0之前,可以使用委托(delegate)来完成这项工作。比如考虑这样一个应用,对数组元素按照一定的规则进行过虑,对于通用模块,可以写成下面这样子: /// </summary> /// <returns></returns> public static int[] FilterArrayOfInt(int[] ints,intFilter fiter) { ArrayList array = new ArrayList(); foreach (int i in ints) { if (fiter(i)) array.Add(i); } return ((int[])array.ToArray(typeof (int))); } } public class AppliationTest { /* * 这个IsOdd()方法,就是描述算法的命名方法(Named Method)。在实际的调用过程中,caller(调用方)调用的是Program类的FilterArrayOfInt()方法,该方法的第二个 * 参数,就是一个过滤算法的委托(函数指针)。所有的过滤算法必须具有相同的参数和返回值类型,在调用FilterArrayOfInt()方法的时候,同时把描述算法的IsOdd()方法 * 做为参数,代入委托,这样就OK了。 */ /// <summary> /// 算法设计人员把过滤算法定义成函数,比如下面这样: /// </summary> /// <param name="i">输入一个数</param> /// <returns></returns> public static bool IsOdd(int i) { return ((i & 1) == 1); } } public class LinqToXmlApplication { public static void ReadXml() { string file = Directory.GetCurrentDirectory();//获取应用程序工作目录 //string file = AppDomain.CurrentDomain.BaseDirectory; XElement elements = XElement.Load(file.Substring(0,file.Length-9)+"Rss.xml"); IEnumerable<XElement> element = from el in elements.Descendants("item") where el.Element("title").Value.Length > 22 select el; foreach (XElement e in element) { Console.WriteLine(e.Element("title").Value); Console.WriteLine("------------------------------------------------------------"); } } } }