问题引出

  这视乎是个完全不必要进行讨论的话题,因为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查询的更多相关文章

  1. .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 ...

  2. C#语法之Linq查询基础一

    Linq做.Net开发的应该都用过,有些地方很复杂的逻辑用Linq很方便的解决.对于Linq to object.Linq to xml.Linq to sql.Linq to Entity(EF)都 ...

  3. LINQ查询数组里面是否包含某值

    #region linq to 数组            //定义数组,并初始化            string [] array = new string []{"Juan" ...

  4. Linq查询基本操作

    摘要:本文介绍Linq查询基本操作(查询关键字) - from 子句 - where 子句 - select子句 - group 子句 - into 子句 - orderby 子句 - join 子句 ...

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

    1.LINQ 函数   1.1.查询结果过滤 :where() Enumerable.Where() 是LINQ 中使用最多的函数,大多数都要针对集合对象进行过滤,因此Where()在LINQ 的操作 ...

  6. Linq查询表达式

    目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...

  7. Linq查询操作语句学习

    对于一个集合,我们通常会用foreach或者for循环来判断查找里面的元素. 但这种方法通常会看起来比较复杂,我们可以使用linq. Linq允许编写C#代码以查询数据库相同的方式操作内存数据(写法类 ...

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

    atitit.  集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby  与 事 ...

  9. Linq查询简介

    查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此, ...

随机推荐

  1. js的单线程和异步

    前言 说到js的单线程(single threaded)和异步(asynchronous),很多同学不禁会想,这不是自相矛盾么?其实,单线程和异步确实不能同时成为一个语言的特性.js选择了成为单线程的 ...

  2. Spark的DataFrame的窗口函数使用

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 SparkSQL这块儿从1.4开始支持了很多的窗口分析函数,像row_number这些,平时写程 ...

  3. php内核分析(二)-ZTS和zend_try

    这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linux ZTS 我们会看到文章中有很多地方是: #ifdef ZTS # define CG(v) ZEND_TSRMG(comp ...

  4. Autofac 的属性注入,IOC的坑

    Autofac 是一款优秀的IOC的开源工具,完美的适配.Net特性,但是有时候我们想通过属性注入的方式来获取我们注入的对象,对不起,有时候你还真是获取不到,这因为什么呢? 1.你对Autofac 不 ...

  5. Vmware虚拟机安装Ubuntu并设置root登陆

    主机操作系统是win7.在Ubuntu官网下好系统镜像.iso文件,安装好Vmware workstation软件 1 安装Ubuntu系统到Vmware虚拟机: 注意下面这步是无法直接设置账号为ro ...

  6. .NET4.5新特性之异步编程(Async和Await)的使用

    一.简介 首先来看看.net的发展中的各个阶段的特性:NET 与C# 的每个版本发布都是有一个"主题".即:C#1.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语 ...

  7. C#开发微信门户及应用(25)-微信企业号的客户端管理功能

    我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理.标签管理.人员管理.以及消息的发送等功能,其中 ...

  8. Mac制作U盘系统(OS X El Capitan)教程

    前言部分 重装过Mac OS X系统的人应该都深有体会,通过自带的重新安装 Mac OS X功能恢复系统(开机时按Command+R) 要耗费10几个小时才能完成(请求苹果国外服务器),但如果通过U盘 ...

  9. 大量数据快速导出的解决方案-Kettle

    1.开发背景 在web项目中,经常会需要查询数据导出excel,以前比较常见的就是用poi.使用poi的时候也有两种方式,一种就是直接将集合一次性导出为excel,还有一种是分批次追加的方式适合数据量 ...

  10. ECharts的简单使用过程

    网页中经常要使用图表,以前使用的是highcharts插件,现在发现echarts使用起来和highcharts差不多,但是个人感觉echarts更酷炫,以下是echarts的使用过程,其实highc ...