LINQ简记(3):子句

 
LINQ查询表达式的子句如select,where,from等都是比较简单的子句,相信各位多练习练习,再结合MSDN的例子,基本上是可以理解的,因此,本文只挑几个有代表性的,以及有些难理解的子句来简述一下。
 
一、where子句。
在SQL中,筛选语句常用的表示方式如“select * from Users where uName = 'DMIN'”,这个SQL语句就带有WHERE子句,其实,在LINQ中也类似,只不过放的位置不一样。请看下面的例子。
 
            int[] Source1 = new int[] { 10, 50, 22, 38, 91, 17 };
            // 筛选出大于20的数字
            var res =
                from n in Source1
                where n > 20
                select n;
            Debug.Write("\n\n大于20的整数有:\n");
            foreach (int x in res)
            {
                Debug.Write("  " + x);
            }


输出的结果为:

 大于20的整数有:
  50  22  38  91


复合条件的写法与if等判断语句一致,LINQ遵循C#语法,再看看下面一个例子,从字符串数组中选出以T开头并且长度大于等于3的。
             string[] Source2 = new string[]{
                "Time", "Apple", "Noooooode", "DogDoorDoc", "TikkyOde"
            };
            var res2 =
                from s in Source2
                where s.StartsWith("T") && s.Length >= 3
                select s;
            Debug.Write("\n\n以“T”开头并且长度在3以上的字符串有:\n");
            foreach (string str in res2)
            {
                Debug.Write("  " + str);
            }


输出结果如下:

 以“T”开头并且长度在3以上的字符串有:
  Time  TikkyOde


 

二、group子句。

这是一个有点儿难度的子句,很多朋友可能搞不清楚它查询后返回的是什么。这样,我们还是用一个例子来说明吧。

首先,声明一个类,包含两个字段:学生姓名和成绩。

     public class Student
    {
        public string Name { get; set; }
        public int Score { get; set; }
    }

接着,我们把学生的名字以首字母进行分组。

             Student[] Source3 = new Student[]{
                new Student{Name="ZhangFeng", Score = 60},
                new Student{ Name = "LiuXiaoShan", Score = 75 },
                new Student{ Name = "LiangWuTai", Score = 80 },
                new Student{ Name = "ZhongNing", Score = 65 },
                new Student{ Name = "FuNan", Score = 71 },
                new Student{ Name = "LanAo", Score = 79 },
                new Student{ Name = "FangTianHao", Score = 88 }
            };
            var res3 =
                from st in Source3
                group st by st.Name[0];

            Debug.Write("\n\n查询结果变量的类型:" + res3.GetType().Name + "\n");
            Debug.Write("\n分别输出各分组的信息:\n");
            foreach (var g in res3)
            {
                Debug.WriteLine("数据类型:" + g.GetType().Name);
            }



调试运行,然后注意查看“输出窗口”中的内容。

 查询结果变量的类型:GroupedEnumerable`3

分别输出各分组的信息:
数据类型:Grouping
数据类型:Grouping
数据类型:Grouping


因此,我们可以得到这样的结果:

1、分组查询返回一个GroupedEnumerable;

2、每个GroupedEnumerable中包含N个Grouping。

我们发现这些类在对象浏览器中找不到,GroupedEnumerable是内部类,但Grouping通过反射也没找着,那它们的结构到底如何?

现在,我们通过断点调试,进一步了解它们。

 
 

从截图中我们看到,IGrouping<TKey,TElement>有一个Key属性,其实它就是存储我们用来进行分组的键,怎么理解呢?

回到上面的例子,我们以什么作为分组的依据?对,姓名字段的第一个个字母,其实是Char类型,因此,比如上面的,“Z”就是一个组的键,在这个组里面,都是以Z开头的对象的集合。

我们可以下一个不成文的结论:分组结果中的所谓Key就是我们用于分组所依据的字段或具体的值。

 

在实现IGrouping<TKey,TElement>的类中,显然会实现GetEnumerator方法,也就是说我们可以把它foreach出来,上图中看到,每个元素(TElement)说白了就是已经被分组的对象,上例中即为Student对象。

而每个组中其实包含Lookup<TKey,TElement>类。

 

呵呵,有些混乱了,我们可以这样总结:

执行了LINQ分组查询后,得到的所有分组的集合A,而A中的每个成员就是一个组G1、G2……而G1中就是被分到该组的对象O1、O2……可能用一个图来表示会直观一点。

 

现在,我们把上面的代码改一下。

             foreach (var g in res3)
            {
                Debug.WriteLine(g.Key);
                foreach (var item in g)
                {
                    Debug.WriteLine("姓名:" + item.Name);
                    Debug.WriteLine("成绩:" + item.Score);
                }
            }


输出结果如下:

 Z
姓名:ZhangFeng
成绩:60
姓名:ZhongNing
成绩:65
L
姓名:LiuXiaoShan
成绩:75
姓名:LiangWuTai
成绩:80
姓名:LanAo
成绩:79
F
姓名:FuNan
成绩:71
姓名:FangTianHao
成绩:88


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值