select 对查询的结果进行投影,在子句中指定要选择的列,如上例。 有的时候,我们只需要投影某一列,我们可以这样 - private static void TestSelectSingleProperty()
- {
- var persons = GetPersons();
- var query = from p in persons
- select p.Name;
- foreach (var item in query)
- {
- Console.WriteLine(item);
- }
- }
复制代码 我们还可以指定要投影的列的集合,这个时候我们要用到匿名类型 - var query = from p in persons
- select new { p.ID, p.Name };
- foreach (var item in query)
- {
- Console.WriteLine("No:{0},Name:{1}",item.ID,item.Name);
- }
复制代码 query中的每一项都时候一个拥有ID属性和Name属性的对象,当然有的时候实体的属性名不是我们想要的,或者是通过对属性计算得来的,那么我们可以显式指定属性名,就像下面这样: - var query = from p in persons
- select new
- {
- UserID = p.ID,
- FriendName = p.Gender == "男" ? "Mr" : "Ms" + p.Name
- };
- foreach (var item in query)
- {
- Console.WriteLine("No:{0},Friendly Name:{1}", item.UserID, item.FriendName);
- }
复制代码 where 对容器内的数据进行筛选。 - var query = from p in persons
- where p.DepartmentID == 1
- select p.Name;
复制代码 join 类似SQL里的join,Linq中的join子句用于将两个容器的数据以某种关系进行关联。 - var departments = GetDepartments();
- var persons = GetPersons();
- var query = from d in departments
- join p in persons on d.ID equals p.DepartmentID
- select new { d, p };
复制代码 值得注意的是join子句只能使用equals或者是not equal而不能用其他运算符(==都不行)。而equals运算符左边必须联接的左部,右边为右部,不能调换的,否则编译不能通过。 into into子句用于将join或者是group子句的结果进一步持续化,包装成为一个 System.Linq.IGrouping<TKey, TElement> 对象,而且IGrouping继承自IEnumerable<TElement>,可以看出,IGrouping接口提供分组的键和,该键下所包含的集合。例子见group group 对结果按照指定的条件进行分组 - var container = new List<string> { "ZhangSan", "LiSi", "Wangwu", "ZhaoLiu", "Deng" };
- var query = from name in container
- group name by name.Length into g
- select new { g.Key, Values = g };
复制代码 例子演示了通过姓名的长度对一个姓名列表进行分组,并将分组的结果保持到局部变量g中,可以通过下面的代码将query的结果输出 - foreach (var group in query)
- {
- Console.WriteLine("{0}:", group.Key);
- foreach (var item in group.Values)
- {
- Console.WriteLine(item);
- }
- }
复制代码 let let子句用于在查询中添加一个新的局部变量,使其在后面的查询中可见 - var query = from p in persons
- let friendlyName = p.Gender == "男" ? "Mr" : "Ms" + p.Name
- select new
- {
- UserID = p.ID,
- FriendName = friendlyName
- };
- foreach (var item in query)
- {
- Console.WriteLine("No:{0},Friendly Name:{1}", item.UserID, item.FriendName);
- }
复制代码 在IEnumerable<T>上的其他扩展 Take Skip 用于选取前XX个或者和跳过前XX个,如选择第11到20个则可以 OrderBy OrderByDescending 排序而已 - query.OrderBy(c => c.Length);
复制代码 Distinct Union Intersect Except 这些单词都见过吧,分别就是取不重复,并集,交集,差集(这个貌似看看参数就明白了) 其他扩展都在Enumerable类下面了。 Linq的延迟加载特性 Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的。从而使Linq查询只是在需要的时候才会被执行。 但是,某一些扩展方法在执行时会试图遍历整个容器,从而使延迟加载无效,如排序,聚合函数(Count,Sum,Average等。) - static IEnumerable<int> InfinityInts()
- {
- int count = 0;
- while (true)
- yield return count++;
- }
- public static void LazyLoad()
- {
- var query = from i in InfinityInts()
- select i;
- foreach (var i in query.Take(20))
- {
- Console.WriteLine(i);
- }
- }
- public static void CantDoLazyLoad()
- {
- var query = from i in InfinityInts()
- select i;
- foreach (var i in query.OrderBy(i => i).Take(20))
- {
- Console.WriteLine(i);
- }
- }
复制代码 这里有个简单的例子来证明,当使用Take时候,Linq语句能正常的执行,而当我们再Linq上使用一个Order By之后,程序就卡死了,当然,这是理所应当的,在失去延迟加载的特性之后,试图对一个无穷序列排序的结果一定是outOfMemory。 最后 文章摘自网络
这都只是皮毛,感兴趣的同学可以自己去MSDN查看更详细的资料,最后,推荐一个工具和一个网站: LINQPAd(http://www.linqpad.net/) 一个非常有用的Linq学习工具 Linq 101 微软官方的Linq样例代码 |