Linq 入门 顺带 Func与Action
Linq的优点:
查询是一种从数据源检索数据的表达式。 查询通常用专门的查询语言来表示。 随着时间的推移,人们已经为各种数据源开发了不同的语言;例如,用于关系数据库的 SQL 和用于 XML 的 XQuery。 因此,开发人员不得不针对他们必须支持的每种数据源或数据格式而学习新的查询语言。 LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况。 在 LINQ 查询中,始终会用到对象。 可以使用相同的基本编码模式来查询和转换 XML 文档、SQL 数据库、ADO.NET 数据集、.NET 集合中的数据以及对其有 LINQ 提供程序可用的任何其他格式的数据。
地址 :https://msdn.microsoft.com/zh-cn/library/bb397906.aspx
深入学习 Linq 我只提个地址 , 不会在复制 , 这样便于日后快速查询
标准查询运算符概述
LINQ(语言集成查询) 导航
带 XML 声明的序列化 也就是保存
C#关键字 关于let的一个帮助理解的小示例: 我们一看就会知道,用了LET之后,层次感会更好一些,代码更易于阅读
int[] numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //传统下的子查询做法 var query = from num in numbers select num * (from n in numbers where n % 2 == 0 select n).Count(); //使用LET关键字的做法 //var query = from num in numbers // let evenNumbers = from n in numbers // where n % 2 == 0 // select n // select num * evenNumbers.Count(); foreach (var item in query) { Console.WriteLine(item); } Console.ReadKey();
-
获取数据源。
-
创建查询。
-
执行查询。
简单的示例:
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // 2. Query creation. // numQuery is an IEnumerable<int> var numQuery = from num in numbers where (num % 2) == 0 select num; // 3. Query execution. foreach (int num in numQuery) { Console.Write("{0,1} ", num); }
数据源
在上一个示例中,由于数据源是数组,因此它隐式支持泛型 IEnumerable<T> 接口。 这一事实意味着该数据源可以用 LINQ 进行查询。 查询在 foreach 语句中执行,因此,foreach 需要 IEnumerable 或 IEnumerable<T>。 支持IEnumerable<T> 或派生接口(如泛型 IQueryable<T>)的类型称为可查询类型。
可查询类型不需要进行修改或特殊处理就可以用作 LINQ 数据源。 如果源数据还没有作为可查询类型出现在内存中,则 LINQ 提供程序必须以此方式表示源数据。 例如,LINQ to XML 将 XML 文档加载到可查询的 XElement 类型中:
// Create a data source from an XML document. // using System.Xml.Linq; XElement contacts = XElement.Load(@"c:\myContactList.xml");
在 LINQ to SQL 中,首先手动或使用 对象关系设计器(O/R 设计器) 在设计时创建对象关系映射。 针对这些对象编写查询,然后由 LINQ to SQL 在运行时处理与数据库的通信。 在下面的示例中,Customers 表示数据库中的特定表,并且查询结果的类型 IQueryable<T> 派生自 IEnumerable<T>。
Northwnd db = new Northwnd(@"c:\northwnd.mdf"); // Query for customers in London. IQueryable<Customer> custQuery = from cust in db.Customers where cust.City == "London" select cust;
有关如何创建特定类型的数据源的更多信息,请参见各种 LINQ 提供程序的文档。 但基本规则非常简单:LINQ 数据源是支持泛型 IEnumerable<T> 接口或从该接口继承的接口的任意对象。
查询
查询指定要从数据源中检索的信息。 查询还可以指定在返回这些信息之前如何对其进行排序、分组和结构化。 查询存储在查询变量中,并用查询表达式进行初始化。 为使编写查询的工作变得更加容易,C# 引入了新的查询语法。
上一个示例中的查询从整数数组中返回所有偶数。 该查询表达式包含三个子句:from、where 和 select。(如果您熟悉 SQL,您会注意到这些子句的顺序与 SQL 中的顺序相反。)from 子句指定数据源,where 子句应用筛选器,select 子句指定返回的元素的类型。 LINQ 查询表达式(C# 编程指南) 一节中详细讨论了这些子句和其他查询子句。 目前需要注意的是,在 LINQ 中,查询变量本身不执行任何操作并且不返回任何数据。 它只是存储在以后某个时刻执行查询时为生成结果而必需的信息。 有关在幕后是如何构建查询的更多信息,请参见标准查询运算符概述
执行查询
延迟执行
如前所述,查询变量本身只是存储查询命令。 实际的查询执行会延迟到在 foreach 语句中循环访问查询变量时发生。此概念称为“延迟执行”,下面的示例对此进行了演示:
// Query execution. foreach (int num in numQuery) { Console.Write("{0,1} ", num); }
foreach 语句也是检索查询结果的地方。 例如,在上一个查询中,迭代变量 num 保存了返回的序列中的每个值(一次保存一个值)。
由于查询变量本身从不保存查询结果,因此可以根据需要随意执行查询。 例如,可以通过一个单独的应用程序持续更新数据库。 在应用程序中,可以创建一个检索最新数据的查询,并可以按某一时间间隔反复执行该查询以便每次检索不同的结果。
强制立即执行
对一系列源元素执行聚合函数的查询必须首先循环访问这些元素。 Count、Max、Average 和 First 就属于此类查询。 由于查询本身必须使用 foreach 以便返回结果,因此这些查询在执行时不使用显式 foreach 语句。 另外还要注意,这些类型的查询返回单个值,而不是 IEnumerable 集合。 下面的查询返回源数组中偶数的计数:
var evenNumQuery = from num in numbers where (num % 2) == 0 select num; int evenNumCount = evenNumQuery.Count();
若要强制立即执行任意查询并缓存其结果,可以调用 ToList<TSource> 或 ToArray<TSource> 方法。
List<int> numQuery2 = (from num in numbers where (num % 2) == 0 select num).ToList(); // or like this: // numQuery3 is still an int[] var numQuery3 = (from num in numbers where (num % 2) == 0 select num).ToArray();
此外,还可以通过在紧跟查询表达式之后的位置放置一个 foreach 循环来强制执行查询。 但是,通过调用 ToList 或ToArray,也可以将所有数据缓存在单个集合对象中。
掌握了 Linq 后 , 就是 是.NET里面的内置委托 Func
这里有篇介绍Func的文章 http://www.cnblogs.com/Gyoung/archive/2013/04/04/2997050.html
主要是最近看开源项目,发现 Func 用户多 , 就来学习下 , 并且 Func 可以与 接 lambda 表达式 , 所以就 放在这里一起做个简单的总结 :
public static void Main() { char[] separators = new char[] {' '}; Func<string, int, string[]> extract = (s, i) => i > 0 ? s.Split(separators, i) : s.Split(separators) ; string title = "The Scarlet Letter"; // Use Func instance to call ExtractWords method and display result foreach (string word in extract(title, 5)) Console.WriteLine(word); }
Func都是有返回类型的,如果我们的方法没有返回类型该怎么办呢?铛铛铛,这时Action就要粉墨登场了。
Action 委托:没有传入参数,也没有返回类型,即Void。如:
static void Main(string[] args) { Action say = SayHello; say(); } public static void SayHello( ) { Console.WriteLine("Say Hello"); }
Action<T> 委托:传入参数为T,没有返回类型。如:
static void Main(string[] args) { Action<string> say = SayHello; say("Hello"); } public static void SayHello(string word ) { Console.WriteLine(word); }
其实Action与Func的用法差不多,差别只是一个有返回类型,一个没有返回类型,当然Action也可以接匿名方法和Lambda表达式。
匿名方法:
static void Main(string[] args) { Action<string> say = delegate(string word) { Console.WriteLine(word); }; say("Hello Word"); }
Lambda表达式:
static void Main(string[] args) { Action<string> say = s => Console.WriteLine(s); say("Hello Word"); }