日期:2014-05-20  浏览次数:20883 次

LinQ由浅入深(二)

Lambda 表达式的由来:
 //定义一个委托
        public delegate string deleTransfer(string s);//签名

 /// <summary>
        /// LambDa 来源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLambDa_Click(object sender, EventArgs e)
        {
            //.net FrameWork 1.0委托——函数指针
           /* deleTransfer dt = new deleTransfer(ToPascal);//委托指向ToPascal方法
            MessageBox.Show(dt("abc"));*/

            //.net FrameWork 2.0匿名方法
            /*deleTransfer dt = delegate(string str) { return str.Substring(0, 1).ToUpper() + str.Substring(1).ToLower(); };
            MessageBox.Show(dt("acccee"));*/

            //.net FrameWork 3.5 方法
           // deleTransfer dt = (str) => (str.Substring(0, 1).ToUpper() + str.Substring(1).ToLower());//dt = (str)定义一个变量str,str是参数,可以不写括号()如下:
            deleTransfer dt = str => str.Substring(0, 1).ToUpper() + str.Substring(1).ToLower();
            MessageBox.Show(dt("acccee"));

        }


Lambda 表达式
 最基本的语法:(参数列表) => {方法体}  //=>代表左边为参数列表(形参列表),右边为方法体,这个表达式自动提供return返回;
 例如:str => str.Substring(0, 1).ToUpper() + str.Substring(1).ToLower();
 上述例子str是作为形参进行传递,传递到 => 中的方法体 ,然后方法体就进行处理。
 注意
  参数列表中的参数类型可以是明确类型或者是推断类型。
  如果是推断类型,则参数的数据类型将由编译器根据上下文自动推断出来。
  (与匿名方法相似,但不同,匿名方法中的参数必须是已定义的,而Lambda是可以推断的。)

基本查询操作符--获取数据
Select()
 语法:
 public static IEnumerable<TRsult> Select <TSource,TResult>(
  this IEnumerable<TSource> source,
  Func<TSource,Tresult> selector
 )
 说明:
 Select 方法本身是一个泛型扩展方法。
 它作用于IEnumerable<TSource>类型,IEnumerable<TSource>是一个可枚举接口,返回值就是这个类型。
 Select <TSource,TResult>,TSource,TResult是参数,传递的参数。
 this IEnumerable<TSource>是指给实现了IEnumerable接口的类都添加一个 Select方法。
 它只接受一个Func<TSource,Tresult> 是一个泛型委托,位于System命令空间下,System.Core.dll中。
 在这里selector是一个提取器。

 

基本查询操作符--过滤数据
Where()
 语法:
 public static IEnumerable<TSource>Wherer <TSource>(
  this IEnumerable<TSource> source,Func<TSource,bool> predicate
 )
 说明:
 Where 方法也是一个泛型扩展方法
 它和Select()一样作用于IEnumerable<TSource>类型
 它只接受一个Fun<TSource,bool>泛型委托参数
 在这里predicate是一个判断条件。

 

基本查询操作符--排序数据
OrderBy()
 语法:
 public static IOrderedEnumerable<TSource> OrderBy <TSource,TKey>(
  this IEnumerble <TSource> source,
  Func<TSource,TKey> keySelector
 )
 说明:
 OrderBy方法也是一个泛型扩展方法
 它和Select()一样作用于IEnumerable<TSource>类型
 它只接受一个 Func<TSource, TKey > 类型参数
 在这里 keySelector 指定要排序的字段
 如果想降序排列可以使用OrderByDescending方法

 

基本查询操作符——分组数据
GroupBy()
 语法:
 public static IEunmerable<IGrouping<TKey,TSource>>GroupBy<TSource,TKey>(
  this IEnumerable<TSource> source,Func<TSource,TKey> keySelector
 )
 说明:
 GroupBy方法和OrderBy方法非常类似,它也是一个泛型扩展方法,注意IEnumerable里再嵌套了一个泛型IGrouping<TKey,TSource>
 它和 OrderBy() 一样作用于IEnumerable<TSource>类型
 它只接受一个 Func<TSource, TKey > 类型参数
 在这里 keySelector 指定要分组的字段


对查询,条件,排序,分组的例子:
  /// <summary>
        /// "点击Select按钮",关于Select的使用
        /// 对数组和集合的使用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelect_Click(object sender, EventArgs e)
        {
            //LinQ to Object
            //泛型集合数据persons
            List<string> persons = new List<string>();
            persons.Add("zhang san");
            persons.Add("zhang san feng");
            persons.Add("li si");
            persons.Add("wang wu");
            persons.Add("li ba");
            persons.Add("lao wu");
            persons.Add("zhang xx");

            //输出persons中所有的元素
            /*var result = persons.Select(p=>p);
            result.Print();*/

            //输出persons中姓zhang的人
            //StartsWith();//确定传递进去的字符串的开头与指定的字符串进行匹配
            //var result = persons.Where(p => p.StartsWith("zhang"));
            //下面的两种写法实现的效果是一样的
            //var result = persons.Select(p => p).Where(p => p.StartsWith("zhang"));
            //var result = persons.Where(p => p.StartsWith("zhang")).Select(p => p);
            //var result = persons.Where(p => Judge(p));

            //排序,默认升序
            //var result = persons.OrderBy(p=>p);
            //按照名字的最后一个字母排序
            //var result = persons.OrderByDescending(p => p);
            //result.Print();

            //按照姓名来分组--取出姓名中的空格前的部分
            var result = persons.GroupBy(p=>p.Split(new char[]{' '})[0]);
            foreach (var group in result)
            {
                Console.WriteLine("姓名:"+group.Key);
                foreach (var item in group)
                {
                    Console.WriteLine("\t"+item);
                }
                Console.WriteLine();
            }
        }

        //可以在这里做复杂的处理,只要确保返回值为bool就可以了。
        public bool Judge(string s)
        {
            if (s.StartsWith("zhang"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
 

    /// <summary>
    /// 拓展类,只要是静态就可以
    /// </summary>
    public static class ExtraClass
    {
        //为IEnumerable提供输出的方法
        public static void Print(this IEnumerable<string> ie)
        {
           IEnumerator<string> result =  ie.GetEnumerator();
           string str = "";
           while (result.MoveNext())
           {
               str+=result.Current+"\t";
           }
           MessageBox.Show(str);
        }
    }

 查询执行的时机:
 查询分为以下三步:获取数据源、定义查询、执行查询;
 定义查询后,查询直到需要枚举结果时才被真正执行,这种方式称为“延迟执行(deferred execution)”;
 当查询方法返回单一值时,查询立即执行;


    声明:本教程大部分内容基于北风网专题培训提取而来。