Linq学习笔记(转)
开始Linq前你要知道的
扩展方法
顾名思义就是对现有类进行扩展的的方法,扩展方法可以在不修改现有类的情况下,为现有类增加公共的接口(不是C#中的interface)。
扩展方法本质上是一个静态方法,不同之处在于它的第一个参数必须有this关键字声明,并且第一个参数的类型即为要扩展的类型。如
public static double ToDouble(this string source)
{
double res = 0d;
double.TryParse(source, out res);
return res;
} public static void SimpleExtesionMethod()
{
double d = "12345.54321".ToDouble();
Console.WriteLine(d);
}
这里是个简单的将字符串转为double类型的扩展方法,只要引用了该方法的命名空间,则都可以直接用string类型来调用ToDouble方法。
扩展方法是后文的基础,C#3.0中的Linq的实现都是基于扩展方法,通过对IEnumerable<T>接口(Linq to Objects)的扩展和对IQueryable<T>的扩展来实现Linq的相关功能,而Linq的相关关键字最终都是转化为对IEnumerable<T>(IQueryable<T>)的调用。
Lambda表达式
lambda表达式其实就是.net2.0中的匿名方法,然后再3.0中以一种更优美的姿态呈现出来。
lambda表达式的基本语法为
(参数列表) =>{语句块;} 或者 ( 参数列表) =>表达式
当参数列表中只有一个参数的时候,圆括号可以省略
Func<string, string> func = x => x + x;
Console.WriteLine(func("a"));
Var:隐式类型化变量
使用与可以由编译器推导出的变量的声明,不需要显式指定对象的类型。
var container = new List<string> { "张三", "李四", "王五" };
IEnumerable<string> query = from name in container
select name;
上例中由于定义中已经指明了对象的类型,声明中已经完全没有必要使用显示的类型定义,所以可以使用var关键字。
对于匿名对象
var test = new { Name = "Sth.", Type = "UnKnown" };
由于无法用一个类型类声明匿名对象,此时可以用var是声明。
注意var只是省下了显式声明的过程,而C#本身就是静态语言,所以var所声明的变量的类型已经确定任然是不能改变的,亦即,var并非是变体类型。
Linq对谁适用
linq的语法通过System.Linq下面的Enumerable类提供支持,通过观察他的签名,你就会发现他为IEnumerable<T>实现了一系列的扩展方法,也就是说,只要是实现了IEnumerable<T>的对象都可以使用Linq的语法来查询。
而对于只实现了IEnumerable接口而没有实现IEnumerable<T>的对象可以通过
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source);
来将IEnumerable接口转为IEnumerable<T>(例如ArrayList)。
Linq中的关键字
在C#3.0中,为Linq引入了一些新的关键字,他们是:
from join where group into let orderby select
熟悉Sql的同学看着是不是有些眼熟呢,其实在Linq中他们的涵义和在SQL中类似的,所以会很容易理解的。接下来的时间,简单介绍下这些关键字的使用。
from
from子句是一个Linq查询的开始,任何一个Linq语句都是以from开始,from子句指定查询的容器,和在此语句有效的局部变量(用来指定容器中的一项,from子句的效果很类似于foreach)。from子句的语法为
from local in container
local就是在此Linq语句中的局部变量,由于container必须为IEnumerable<T>,他的类型可以由container推导出来(即T)。上一段简单的例子:
ar container = new List<string> { "张三", "李四", "王五" };
var query = from name in container
select name; foreach (string name in query)
{
Console.WriteLine(name);
}
输出:
张三
李四
王五
如果container仅仅实现IEnumerable而没有实现IEnumerable<T>,则需要显式指定局部变量的类型,或者是使用Cast转为IEnumerable<T>
var container = new ArrayList { "张三", "李四", "王五" };
var query = from name in container.Cast<string>()
select name;
//或者
var query1 = from string name in container
select name;
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 ==
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个则可以
query.Skip().Take();
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 = ;
while (true)
yield return count++;
} public static void LazyLoad()
{
var query = from i in InfinityInts()
select i;
foreach (var i in query.Take())
{
Console.WriteLine(i);
}
} public static void CantDoLazyLoad()
{
var query = from i in InfinityInts()
select i;
foreach (var i in query.OrderBy(i => i).Take())
{
Console.WriteLine(i);
}
}
这里有个简单的例子来证明,当使用Take时候,Linq语句能正常的执行,而当我们再Linq上使用一个Order By之后,程序就卡死了,当然,这是理所应当的,在失去延迟加载的特性之后,试图对一个无穷序列排序的结果一定是outOfMemory。
Linq学习笔记(转)的更多相关文章
- linq学习笔记
最近在学习linq的一些基础知识,看了c#高级编程及阅读了园子内部几篇优秀的博文,有所体会,感觉应该记录下来,作为以后复习使用.都是一些最基础的知识,大致分为三个部分:linq预备知识:linq查询: ...
- (转)Linq学习笔记
写在前面 最近在看Linq,在博客园看到这篇文章,写的通俗易懂,转来和大家一起做个分享.原文地址http://www.cnblogs.com/goscan/archive/2011/05/05/Lin ...
- C#之Linq学习笔记【转】
写在前面 其实在09年就已经学习过Linq了,并被她那优美的语法所吸引,只是现在所在的公司还在使用VS2005在.Net2.0的框架下面的开发,所以Linq也很久没有用过了,最近看部门的同事对这个有些 ...
- C# Linq 学习笔记
刚刚学习了 Siki老师 的C#教程Linq部分,以下是笔记 需要引用命名空间 using System.Linq; 然后我们需要准备数据 武林高手类 /// <summary> /// ...
- C# LINQ学习笔记一:走进LINQ的世界
本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5832322.html,记录一下学习过程以备后续查用. LINQ 简介: 语言集成查询(LINQ)是Vi ...
- LINQ 学习笔记(1)
学习资源参考 : http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html 常用方法是 Where, OrderBy, Selec ...
- C# LINQ学习笔记五:LINQ to XML
本笔记摘抄自:https://www.cnblogs.com/yaozhenfa/p/CSharp_Linq_For_Xml.html,记录一下学习过程以备后续查用. 一.生成xml 1.1创建简单的 ...
- C# LINQ学习笔记四:LINQ to OBJECT之操作文件目录
本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5816051.html,记录一下学习过程以备后续查用. 许多文件系统操作实质上是查询,因此非常适合使用LINQ方 ...
- C# LINQ学习笔记三:LINQ to OBJECT之操作字符串
本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5814204.html,记录一下学习过程以备后续查用. 一.统计单词在字符串中出现的次数 请注意,若要执行计数, ...
- C# LINQ学习笔记二:LINQ标准查询操作概述
本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5801249.html,记录一下学习过程以备后续查用. “标准查询运算符”是组成语言集成查询 (LINQ) 模式 ...
随机推荐
- phonegap + Framework7 之 ios 推送跳转测试
先说说项目情况:使用phonegap创建的ios项目,然后在使用html + css开发网页中又使用了一个框架Framework7(Framework7是一个构建仿原生ios和android应用的框架 ...
- No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=i386)
今天在运行一个老ios项目的时候,突然报错:No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VAL ...
- mac 终端启动 jboss 停留在(Starting) 不能启动joss
今天下载了jboss,解压后发现standalone.sh,不能够在终端中执行,于是google了一下,原来是由于jdk版本的问题导致jboss一直停在调试状态(貌似是这样说的). 需要把mac系统的 ...
- 移动Web开发(二)
这些天一直在忙iOS,Android和.Net方面的知识都有些忘记了,汗.不过还是先重温一下HTML吧,手动滑稽. 说实话前面的基础部分基本上大家都会,就当看个热闹吧. 1.HTML的核心要素--标签 ...
- store 加载异常处理与加载信息提示
var msgTip = ''; // 一定要定义在使用前,且定义为全局变量 /--------------------------------store--------------------- ...
- 转:无法向会话状态服务器发出会话状态请求请。确保 ASP.NET State Service (ASP.NET 状态服务)已启动
今天看到一篇文章感觉不错,收藏转载下. 原文地址:http://blog.csdn.net/sntyy/article/details/2090347 版权为原作者所有 无法向会话状态服务器发出会话状 ...
- HTML5设计网页动态条幅广告(Banner) 已经加上完整源代码
横幅广告(Banner): 1.横幅广告是网络广告的常见形式,一般位于网页的醒目位置上:当用户单击这些横幅广告时,通常可以链接到相应的广告页面: 2.设计横幅广告时,要力求简单明了,能够体现出主要的中 ...
- DbUtils是Apache出品一款简化JDBC开发的工具类
DbUtils - DbUtils是Apache出品一款简化JDBC开发的工具类 - 使用DbUtils可以让我们JDBC的开发更加简单 - DbUtils的使用: ...
- C# 重载运算符
如果你想让自己定义的类型可以用运算符进行运算,那么可以通过重载运算符来实现: 示例: class Salary { public int RMB { get; set; } public static ...
- mysql优化案例分析
本文总结了一些工作常见的sql优化例子,虽然比较简单,但很实用,希望对大家有所帮助.sql优化一般分为两类,一类是sql本身的优化,如何走到合适的索引,如何减少排序,减少逻辑读:另一类是sql本身没有 ...