• 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、Queryable两个类。

    一、IEnummerable<T>和IQueryable<T>区别

    using System.Runtime.InteropServices;
    
    namespace System.Collections
    {
        //
        // 摘要:
        //     公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。
        [ComVisible(true)]
        [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
        public interface IEnumerable
        {
            //
            // 摘要:
            //     返回一个循环访问集合的枚举器。
            //
            // 返回结果:
            //     可用于循环访问集合的 System.Collections.IEnumerator 对象。
            [DispId(-4)]
            IEnumerator GetEnumerator();
        }
    }
    using System.Collections;
    using System.Linq.Expressions;
    
    namespace System.Linq
    {
        //
        // 摘要:
        //     提供对未指定数据类型的特定数据源的查询进行计算的功能。
        public interface IQueryable : IEnumerable
        {
            //
            // 摘要:
            //     获取在执行与 System.Linq.IQueryable 的此实例关联的表达式目录树时返回的元素的类型。
            //
            // 返回结果:
            //     一个 System.Type,表示在执行与之关联的表达式目录树时返回的元素的类型。
            Type ElementType { get; }
            //
            // 摘要:
            //     获取与 System.Linq.IQueryable 的实例关联的表达式目录树。
            //
            // 返回结果:
            //     与 System.Linq.IQueryable 的此实例关联的 System.Linq.Expressions.Expression。
            Expression Expression { get; }
            //
            // 摘要:
            //     获取与此数据源关联的查询提供程序。
            //
            // 返回结果:
            //     与此数据源关联的 System.Linq.IQueryProvider。
            IQueryProvider Provider { get; }
        }
    }

    看它们两个的定义也能看出IQueryable继承IEnumerable,那两者什么区别呢?那我们可以看下两个接口的扩展类Enumerable、Queryable。

    这两个类API相同,但是仔细看可以发现参数类型不一样,一个是Fuc<> 一个是Expression<Fuc<>>,其实Queryable是对Linq to sql、EF来使用的,虽然对外的api是一样的,但实现的原理是不一样的,一个是func<>lamdbs表达式,一个是Expression<Fuc<>>表达式树。

    二、Linq基础查询

    前面区分了两个接口,但API是一样的,查询用法也是一样,只是提高数据源的方式不一样。所以先抛开不一样的,求同存异嘛,下面主要是讲一下一样的部分。

    上面是在百科上下的图片,虽然我也没看明白这个图,但在下面的几篇博客中我会把Linq查询的基本用法都列举出来,今天这篇博客只是对Linq做一简单介绍。

    1.方法语法、查询语法

    书写LINQ查询时又两种语法可供选择:方法语法(Fluent Syntax)和查询语法(Query Expression)。

    LINQ方法语法是非常灵活和重要的,我们在这里将描述使用链接查询运算符的方式来创建复杂的查询,方法语法的本质是通过扩展方法和Lambda表达式来创建查询。C# 3.0对于LINQ表达式还引入了声明式的查询语法,通过查询语法写出的查询比较类似于SQL查询。本篇会对LINQ方法语法进行详细的介绍。

    当然,.NET公共语言运行库(CLR)并不具有查询语法的概念。所以,编译器会在程序编译时把查询表达式转换为方法语法,即对扩展方法的调用。所以使用方法语法会让我们更加接近和了解LINQ的实现和本质,并且一些查询只能表示为方法调用,如检索序列中的最大值、最小值元素的查询,他们在查询语法中就没有对应的实现。但另一方面,查询语法通常会比较简单和易读。不管怎样,这两种语法和互相补充和兼容的,我们可以在一个查询中混合使用方法语法和查询语法。

    比如直接.List.where(p=>XX)这种是方法语法, from p in list XXXX这种是查询语法,查询语法还是转换为方法语法。

    2.延迟计算

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace LinqDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                int[] a = new int[] { 1,3,5,7,9,11,2,4,6};
                int b = 3;
                var result = from p in a where p % b == 0 select p;
    
                foreach (var m in result)
                {
                    Console.WriteLine(m);
                }
                Console.WriteLine("-------------------------");
                b = 2;
                foreach (var m in result)
                {
                    Console.WriteLine(m);
                }
                Console.ReadLine();
            }
        }
    }

    上面代码第一次是b=3,照数组a中3的倍数的数字,输出是2、9、6,但当把b改为2时,再次输出结果发现输出的是2、4、6,这个例子主要说明Linq是延迟计算,和其他地方的懒加载是一样的,声明的时候并不会直接计算出来,而是等到用时在计算。

  • 相关阅读:
    创建git项目的feature分支以及下载特定分支的仓库代码
    C++读取文件
    linux解压eclipse启动时无法找到jre环境的解决办法
    ubuntu安装谷歌浏览器
    web项目脱离Eclipse在Tomcat部署并配置Eclipse调试
    阿里巴巴连接池Druid简单使用
    gc overhead limit exceeded
    onload方法注意点
    获取Spring管理的Bean
    Java应用中使用ShutdownHook友好地清理现场
  • 原文地址:https://www.cnblogs.com/5ishare/p/5770369.html
Copyright © 2020-2023  润新知