问题引出

  这视乎是个完全不必要进行讨论的话题,因为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. linux su和sudo命令的区别

    一. 使用 su 命令临时切换用户身份 1.su 的适用条件和威力 su命令就是切换用户的工具,怎么理解呢?比如我们以普通用户beinan登录的,但要添加用户任务,执行useradd ,beinan用 ...

  2. 跨域之jsonp

    我们都知道使用<script>标签可以引入外部的JS文件,即使这个JS文件来自于其他的网站,比如我们引用存放在网络服务器上的jQuery框架.在这个过程中,我们已经实现跨域访问.像< ...

  3. 从零自学Hadoop(20):HBase数据模型相关操作上

    阅读目录 序 介绍 命名空间 表 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 ...

  4. LCS记录

    如题:求两个序列的最长公共序列.(如:"ABCBDAB"与"BCDB"最长公共序列为"BCDB")代码如下: #define MAX_SIZ ...

  5. 【无私分享:ASP.NET CORE 项目实战(第九章)】创建区域Areas,添加TagHelper

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在Asp.net Core VS2015中,我们发现还有很多不太简便的地方,比如右击添加视图,转到试图页等功能图不见了,虽然我 ...

  6. 周末惊魂:因struts2 016 017 019漏洞被入侵,修复。

    入侵(暴风雨前的宁静) 下午阳光甚好,想趁着安静的周末静下心来写写代码.刚过一个小时,3点左右,客服MM找我,告知客户都在说平台登录不了(我们有专门的客户qq群).看了下数据库连接数,正常.登录阿里云 ...

  7. Java transient关键字

    Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...

  8. CSS3学习总结——实现瀑布流布局与无限加载图片相册

    首先给大家看一下瀑布流布局与无限加载图片相册效果图: 一.pic1.html页面代码如下: <!DOCTYPE html> <html> <head> <me ...

  9. 正确制作一个iframe,认识iframe

    iframe作为一个网站之间交互的桥梁,受到很多站长的喜爱,但是又有不安全的因素存在,所以正确填写属性是很重要的. <iframe name="my_iframe" heig ...

  10. ASP.NET的六大内置对象

    ASP.NET 六大内置对象(System.Web.UI.Page类): 1.Response 2.Request 3.Server 4.Application 5.Session 6.Cooki R ...