Fork me on GitHub

LINQ基础知识

议程

1.LINQ和LINQ表达式

2.Lambda表达式

两个接口

IEnumerable <T> 泛型接口

公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代。

public class MyCollections<T> : IEnumerable<T>

{

T[] values = new T[100];

public IEnumerator<T> GetEnumerator()

{

for (int i = 0; i < 100; i++)

{

yield return values[i];

}

}

IEnumerator IEnumerable.GetEnumerator()

{

return GetEnumerator();

}

}

class Class2

{

static void Main()

{

MyCollections<int> Mycol = new MyCollections<int>();

foreach (int i in Mycol)

{

Console.WriteLine(i);

}

}

}

Iqueryable<T>

提供对数据类型已知的特定数据源的查询进行计算的功能。

此接口继承 IEnumerable<T>接口,因此,如果它表示一个查询,则可以枚举该查询的结果。枚举强制执行与 Iqueryable<T>对象关联的表达式目录树。

LINQ基本概念

LINQ:语言集成查询(Language Integrated Query),是一系列标准查询操作符的集合,这些操作符几乎对每一种数据源的导航,过滤和执行都是提供了底层的基本查询架构。

LINQ可查的数据源包括关系数据,XML,DataSet或内存中的数据。

LINQ出现的背景:大多数开发人员对OO的熟悉,最好提把对数据的操作转化成对对象的操作。

LINQ恰好将标准查询功能直接整合到了供开发人员选择的基于.NET的编程语言中。

LINQ支术的重点是查询表达式,因为它描述了对数据源的具体操作。

LINQ查询表达式基本概念

1.查询表达式可用于查询和转换来自任意支持 LINQ 的数据源中的数据。例如,单个查询可以从 SQL 数据库检索数据,并生成 XML 流作为输出。

2.查询表达式容易掌握,因为它们使用许多常见的 C# 语言构造。

3.查询表达式中的变量都是强类型的,但许多情况下您不需要显式提供类型,因为编译器可以推断类型。

4.在您循环访问 foreach 语句中的查询变量之前,不会执行查询。

5.在编译时,根据 C# 规范中设置的规则将查询表达式转换为“标准查询运算符”方法调用。任何可以使用查询语法表示的查询也可以使用方法语法表示。但是,在大多数情况下,查询语法更易读和简洁。

6.作为编写 LINQ 查询的一项规则,建议尽量使用查询语法,只在必需的情况下才使用方法语法。这两种不同形式在语义或性能上没有区别。查询表达式通常比用方法语法编写的等效表达式更易读。

7.一些查询操作,如 Count 或 Max,没有等效的查询表达式子句,因此必须表示为方法调用。方法语法可以通过多种方式与查询语法组合。

8.查询表达式可以编译为表达式目录树或委托,具体取决于查询所应用到的类型。IEnumerable<(Of <(T>)>) 查询编译为委托。IQueryable 和 IQueryable<(Of <(T>)>) 查询编译为表达式目录树。

LINQ查询表达式

查询操作包含三部分:

  1. 获取数据源
  2. 创建查询
  3. 执行查询

Demo:

//获取数据源

string[] Devices= {"电视" ,"电冰箱","洗衣机","电话","微波炉"};

//创建查询

var SelectDevices = from device in Devices

where device.StartsWith("电")

select device;

//执行查询

foreach (string dev in SelectDevices)

{

Console.WriteLine("带电的设备:{0}",dev);

}

匿名方法

在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法。C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式。不过,本主题中有关匿名方法的信息同样也适用于 Lambda 表达式。有一种情况下,匿名方法提供了 Lambda 表达式中所没有的功能。匿名方法使您能够省略参数列表,这意味着可以将匿名方法转换为带有各种签名的委托。这对于 Lambda 表达式来说是不可能的。

button1.Click += delegate(System.Object o, System.EventArgs e)//匿名方法参数

{//匿名方法方法体

MessageBox.Show("Click!");

}; 

 

 

Lambda表达式

  • “Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。
  • 所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x times x”。可以将此表达式分配给委托类型

static void Main()

{

del myDelegate = x => x * x;

int j = myDelegate(5); //j = 25

Console.WriteLine(j);

}

delegate int del(int i);

  • 只有在 Lambda 有一个输入参数时,括号才是可选的;否则括号是必需的。两个或更多输入参数由括在括号中的逗号分隔:

(x, y) => x == y

  • 有时,编译器难于或无法推断输入类型。如果出现这种情况,您可以按以下示例 中所示方式显式指定类型:

(int x, string s) => s.Length > x

uLambda 语句与 Lambda 表达式类似,只是语句括在大括号中:

delegate void TestDelegate(string s);

TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };

myDel("Hello");

  • 在编写 Lambda 时,通常不必为输入参数指定类型,因为编译器可以基于 Lambda 主体、基础委托类型以及 C# 3.0 语言规范中描述的其他因素推断类型。对于大多数标准查询运算符,第一个输入是源序列中的元素的类型。因此,如果要查询 IEnumerable<Customer>,则输入变量将被推断为 Customer类型,这意味着您可以访问其方法和属性:

customers.Where(c => c.City == "London");

  • 有时,编译器难于或无法推断输入类型。如果出现这种情况,您可以按以下示例 中所示方式显式指定类型:

(int x, string s) => s.Length > x

uLambda 语句与 Lambda 表达式类似,只是语句括在大括号中:

delegate void TestDelegate(string s);

TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };

myDel("Hello");

  • 在编写 Lambda 时,通常不必为输入参数指定类型,因为编译器可以基于 Lambda 主体、基础委托类型以及 C# 3.0 语言规范中描述的其他因素推断类型。对于大多数标准查询运算符,第一个输入是源序列中的元素的类型。因此,如果要查询 IEnumerable<Customer>,则输入变量将被推断为 Customer类型,这意味着您可以访问其方法和属性:

customers.Where(c => c.City == "London");

Lambda 的一般规则如下:

  • Lambda 包含的参数数量必须与委托类型包含的参数数量相同。
  • Lambda 中的每个输入参数必须都能够隐式转换为其对应的委托参数。
  • Lambda 的返回值(如果有)必须能够隐式转换为委托的返回类型。

Lambda 可以引用“外部变量”,这些变量位于在其中定义 Lambda 的封闭方法或类型的范围内。将会存储通过这种方法捕获的变量以供在 Lambda 表达式中使用,即使变量将以其他方式超出范围或被作为垃圾回收。必须明确地分配外部变量,然后才能在 Lambda 表达式中使用该变量。

  • 捕获的变量将不会被作为垃圾回收,直至引用变量的委托超出范围为止。
  • 在外部方法中看不到 Lambda 表达式内引入的变量。
  • Lambda 表达式无法从封闭方法中直接捕获 ref 或 out 参数。
  • Lambda 表达式中的返回语句不会导致封闭方法返回。
  • Lambda 表达式不能包含其目标位于所包含匿名函数主体外部或内部的 goto 语句、break 语句或 continue 语句。

查询语法和方法语法

string[] Devices= {"电视" ,"电冰箱","洗衣机","电话","微波炉"};

查询语法

var SelectDevices = from device in Devices

where device.StartsWith("电")

select device;

方法语法

var SelectDevices =Devices .Where ( device => device.StartsWith("电"))

foreach (string dev in SelectDevices)

{

Console.WriteLine("带电的设备:{0}",dev);

}

image

posted @ 2009-08-24 09:26  桂素伟  阅读(1585)  评论(0编辑  收藏  举报