数组为什么可以使用linq查询

问题引出

  这视乎是个完全不必要进行讨论的话题,因为linq(这里具体是linq to objects)本来就是针对集合类型的,数组类型作为集合类型的一种当然可以使用了。不过我还是想写一下,这个问题源于qq群里一位朋友的提问:.net的数组类型都隐式继承了Array类,该类是一个抽象类,并且实现了IEnumerable、ICollection、IList接口。但linq的方法都是针对实现了IEnumerable<T>泛型接口的,Array类并没有实现这些泛型接口,为什么可以使用这些方法呢?

  linq to objects的本质是通过扩展方法来实现集合的查询,这些扩展方法定义在一个Enumerable的静态类中。Enumerable类下的所有扩展方法的第一个参数都是IEnumerable<T> 类型,表示它可以通过IEnumerable<T>类型进行调用。

浅析数组类型

1. 所有数组类型都隐式派生自Array

  当我们定义一个FileStream[] 数组时,CLR会为当前的AppDomain创建一个FileStream[] 类型,该类型派生自 Array。所以数组是引用类型,在堆中分配内存空间。Array类是一个抽象类,定义了许多关于常用的实例方法和静态方法,供所有的数组类型使用。例如常见的:Length属性,CopyTo方法等等。

2. 所有的数组类型都隐式实现了IEnumerable<T>接口

  就如上面所所的,这是一个理所当然的问题,为了提高开发效率,数组类型理应可以使用linq进行查询。但由于数组可以是多维数组或者非0基数组,所以Array类并没有实现IEnumerable<T>、ICollection<T>、IList<T> 这几个泛型接口,而只是实现了非泛型版本的。实际上,CLR会自动为一维的数组类型实现这些泛型接口(指定T类型参数的具体类型),并且还会为它们的父类实现。例如我们定义一个FileStream[] 数组类型,那么CLR会为我们创建如下的层次类型结构:

                              

由于CLR的隐式实现,才使我们可以将一维数组类型应用在需要IEnumerable<T>泛型接口的地方。

  按照上面的说法,我们可以将FileStream[] 类型的对象传递给如下的方法:

  void F1(IEnumerable<object> oEnumerable);

  void F2(ICollection<Stream> sCollection);

  void F3(IList<FileStream> fList);

  这是对于引用类型而言的,如果是值类型,则不为会它的基类实现这些接口。例如DateTimel类型(基类包括ValueType和Object),DateTime[]数组类型不能传递给上面的F1方法,这是因为值类型的数组的内存布局与引用类型的数组不同。

以上图片由“图斗罗”提供

时间: 2024-08-27 23:10:12

数组为什么可以使用linq查询的相关文章

C#语法之Linq查询基础一

Linq做.Net开发的应该都用过,有些地方很复杂的逻辑用Linq很方便的解决.对于Linq to object.Linq to xml.Linq to sql.Linq to Entity(EF)都可以使用linq查询.不知道大家有没有想过为什么linq对这些都可以使用呢?统一的api适用这么多.其实主要还是IEnummerable<T>和IQueryable<T>两个接口.可能有人会问为什么是两个接口?这两个接口有什么区别或者联系呢?这又要引出来Enummerable.Quer

Linq查询操作语句学习

对于一个集合,我们通常会用foreach或者for循环来判断查找里面的元素. 但这种方法通常会看起来比较复杂,我们可以使用linq. Linq允许编写C#代码以查询数据库相同的方式操作内存数据(写法类似于SQL) 核心目标是让程序员关心What,而不是How,所以效率通常不及不用Linq的实现. 但Linq的代码非常易理解,并且可以写的非常简洁.一般的,可以使用Select.Where.OrderBy.GroupBy条件表达式 有这么一个字符串数组: string[] myTest = new

Linq学习之旅——LINQ查询表达式

1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. 概述 LINQ的全称是Language Integrated Query,中文译成“语言集成查询”.LINQ作为一种查询技术,首先要解决数据源的封装,大致使用了三大组件来实现这个封装,分别是LINQ to Object.LINQ to ADO.NET.LINQ to XML.它们和.NET语言的关系如下:

LINQ查询表达式基础

LINQ,语言集成查询(Language Integrated Query)是一组用C#和Visual Basic语言的扩展. 对于编写查询的开发人员来说,LINQ 最明显的"语言集成"部分是查询表达式.查询表达式是使用 C# 3.0 中引入的声明性查询语法编写的.通过使用查询语法,你甚至可以使用最少的代码对数据源执行复杂的筛选.排序和分组操作.你使用相同的基本查询表达式模式来查询和转换 SQL 数据库.ADO.NET 数据集.XML 文档和流以及 .NET 集合中的数据. 下面我们通

Linq查询简介

查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此,开发人员不得不针对他们必须支持的每种数据源或数据格式而学习新的查询语言. LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况. 在 LINQ 查询中,始终会用到对象. 可以使用相同的基本编码模式来查询和转换 XML 文档.SQL 数据库.ADO.NET 数据集..NET

atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php

atitit.  集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby  与 事先排序 2 3. #----------聚合函数 2 4. 自定义linq查询Linq .from(li) .groupBy("url","user" ) .select("url", count().as("countx"), 

LINQ:开始使用 LINQ(一)- 介绍 LINQ 查询

开始使用 LINQ (一)- 介绍 LINQ 查询 查询是一种从数据源检索数据的表达式. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此,开发人员不得不针对他们必须支持的每种数据源或数据格式而学习新的查询语言. LINQ 通过提供一种跨数据源和数据格式使用数据的一致模型,简化了这一情况.在 LINQ 查询中,始终会用到对象.可以使用相同的编码模式来查询和转换 XML 文档.SQL 数据库.ADO.NET 数据集..N

C#基础:LINQ 查询函数整理

1.LINQ 函数 1.1.查询结果过滤 :where() Enumerable.Where() 是LINQ 中使用最多的函数,大多数都要针对集合对象进行过滤,因此Where()在LINQ 的操作上处处可见,Where()的主要任务是负责过滤集合中的数据:其原型如下: 1 public static IEnumerbale<TSouce> Where<TSource>(this IEnumerable<Tsource> source,Func<TSource,bo

C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询

1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法和属性等.Attributes和Microsoft .NET Framework文件的元数据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为.例如,在一个方法前标注[Obsolete]特性,则调用该方法时VS则会提示该方法已过期的警告,如下图: 又如,在.Net Re