数组为什么可以使用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方法,这是因为值类型的数组的内存布局与引用类型的数组不同。
数组为什么可以使用linq查询的更多相关文章
- .net 反射访问私有变量和私有方法 如何创建C# Closure ? C# 批量生成随机密码,必须包含数字和字母,并用加密算法加密 C#中的foreach和yield 数组为什么可以使用linq查询 C#中的 具名参数 和 可选参数 显示实现接口 异步CTP(Async CTP)为什么那样工作? C#多线程基础,适合新手了解 C#加快Bitmap的访问速度 C#实现对图片文件的压
以下为本次实践代码: using System; using System.Collections.Generic; using System.ComponentModel; using System ...
- C#语法之Linq查询基础一
Linq做.Net开发的应该都用过,有些地方很复杂的逻辑用Linq很方便的解决.对于Linq to object.Linq to xml.Linq to sql.Linq to Entity(EF)都 ...
- LINQ查询数组里面是否包含某值
#region linq to 数组 //定义数组,并初始化 string [] array = new string []{"Juan" ...
- Linq查询基本操作
摘要:本文介绍Linq查询基本操作(查询关键字) - from 子句 - where 子句 - select子句 - group 子句 - into 子句 - orderby 子句 - join 子句 ...
- C#基础:LINQ 查询函数整理
1.LINQ 函数 1.1.查询结果过滤 :where() Enumerable.Where() 是LINQ 中使用最多的函数,大多数都要针对集合对象进行过滤,因此Where()在LINQ 的操作 ...
- Linq查询表达式
目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...
- Linq查询操作语句学习
对于一个集合,我们通常会用foreach或者for循环来判断查找里面的元素. 但这种方法通常会看起来比较复杂,我们可以使用linq. Linq允许编写C#代码以查询数据库相同的方式操作内存数据(写法类 ...
- atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php
atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby 与 事 ...
- Linq查询简介
查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此, ...
随机推荐
- 细谈Slick(5)- 学习体会和将来实际应用的一些想法
通过一段时间的学习和了解以及前面几篇关于Slick的讨论后对Slick这个函数式数据库编程工具有了些具体的了解.回顾我学习Slick的目的,产生了许多想法,觉着应该从实际的工作应用角度把我对Slick ...
- Socket简单使用
客户端代码: import java.io.*; import java.net.*; public class DailyAdviceClient { public void go(){ try{ ...
- TFFS格式化到创建成功过程
True FFS内核编程 1.格式化FLASH 即使FLASH没有和块设备驱动绑定,也可对其进行格式化. tffsDevFormat (int tffsDriveNo, int formatArg); ...
- 移动端嵌入pdf.js远程请求pdf出现(206)
最近在做移动端的开发,需要嵌入pdf进行预览.看了很多的js组件后选择了pdf.js:使用起来还是比较方便的,至于使用网上有很多的教程. 但在使用过程中出现了如下一个问题(我做的是IOS系统): 问题 ...
- 最快让你上手ReactiveCocoa之基础篇
前言 很多blog都说ReactiveCocoa好用,然后各种秀自己如何灵活运用ReactiveCocoa,但是感觉真正缺少的是一篇如何学习ReactiveCocoa的文章,这里介绍一下. 1.Rea ...
- Appfuse:权限控制
Appfuse的权限控制依赖于Struts的Menu机制,common下的menu.jsp是对菜单顺序的定义,详细的菜单项和菜单链接及权限再menu-config.xml中控制,如下: <Men ...
- jsonp跨域请求
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 简易版自定义BaseServlet
这几天在学Java Web,一直在思考Servlet重用的问题,就用java的反射机制实现自定义的简易版BaseServlet; 该方式有点像struts2 利用映射获取前端的参数.有兴趣的同学可以自 ...
- HTML之DocType的几种类型 -转载
HTML之DocType的几种类型转载 doctype类型详细doctype的几种类型html之doctype 分类: 前端文摘 在默认情况下,FF和IE的解释标准是不一样的,也就是说,如果一个网页 ...
- 几大排序算法的Java实现
很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...