zoukankan      html  css  js  c++  java
  • [C# 基础知识系列]专题十六:Linq介绍

    转自http://www.cnblogs.com/zhili/archive/2012/12/24/Linq.html

    本专题概要:

    • Linq是什么
    • 使用Linq的好处在哪里
    • Linq的实际操作例子——使用Linq遍历文件目录
    • 小结

     引言:

       终于到了C# 3中最重要特性的介绍了,可以说之前所有介绍的特性都是为了Linq而做准备的,然而要想深入理解Linq并不是这个专题可以介绍完的,所以我打算这个专题将对Linq做一个简单的介绍,对于Linq的深入理解我将会后面单独作为一个系列要和大家分享下。

     一、Linq是什么?

     Linq也就是Language Integrated Query的缩写,即语言集成查询,是微软在.Net 3.5中提出的一项新技术, Linq主要包含4个组件——Linq to Objects、Linq to XML、Linq to DataSet 和Linq to SQL。在这里不会具体介绍这4个组件的内容,只会给出一个大致的介绍, 下面先看看Linq的一个架构图,希望可以让大家可以对Linq有一个全面的认识:

     

     下面简单介绍下四个组件:

    • Linq to SQL 组件——可以查询基于关系数据的数据(微软本身只是实现了对SQL Server的查询,可以对数据库中的数据进行查询,修改,插入,删除,排序等操作
    • Linq to Dataset组件——可以查询DasaSet对象中的数据,并对数据进行增删改查的操作
    • Linq to Objects组件——可以查询IEnumberable 或IEnumberable<T>集合
    • Linq to XML 组件——可以差选和操作XML文件,比Xpath操作XML更加方便

    二、使用Linq的好处在哪里

     第一部分中说到Linq中包括四个组件,分别是对不同数据进行增删改查的一些操作,然而以前也是有相关技术来对这些数据进行操作,(例如,对数据库的操作,之前有Ado.Net 对其进行支持,对XML的操作,之前也可以XPath来操作XML文件等), 此时应该大家都会有个疑问的——为什么以前都有相关的技术对其进行支持,那我们为什么还需要Linq呢?对于这个疑问答案很简单,Linq 使操作这些数据源更加简单,方便和易于理解,之前的技术操作起来过于繁琐,所以微软也有上进心啊,希望可以做的更好啊,所以就在C# 3中提出了Linq来方便大家操作这些数据源,下面通过对比来说明Linq是如何简单方便:

    2.1 查询集合中的数据

    之前我们查询集合中的数据一般会使用for或foreach语句来进行查询,而Linq 使用查询表达式来进行查询,Linq 表达式比之前用for或forach的方式更加简洁,比较容易添加筛选条件,下面就具体看看两者方式的比较代码(我们这里假设一个场景——返回集合中序号为偶数的元素)

     使用foreach 语句来返回序号为偶数的元素的实现代码如下:

    复制代码
    static void Main(string[] args)
            {
                #region Linq to objects 对比
                Console.WriteLine("使用老方法来对集合对象查询,查询结果为:");
                OldQuery();
                Console.WriteLine("使用Linq方法来对集合对象查询,查询结果为:");
                LinqQuery();
                Console.Read();
         
                #endregion
            }
           #region Linq to Objects对比
    
            // 使用Linq 和使用Foreach语句的对比
    
            // 1. 使用foreach返回集合中序号为偶数的元素
            private static void OldQuery()
            {
                // 初始化查询的数据
                List<string> collection = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    collection.Add("A"+i.ToString());
                }
              
                // 创建保存查询结果的集合
                List<string> queryResults = new List<string>();
                foreach (string s in collection)
                {
                    // 获取元素序号
                    int index = int.Parse(s.Substring(1));
                    // 查询序号为偶数的元素
                    if (index % 2 == 0)
                    {
                        queryResults.Add(s);
                    }
                }
    
                // 输出查询结果
                foreach (string s in queryResults)
                {
                    Console.WriteLine(s);
                }
            }
    
            // 2. 使用Linq返回集合中序号为偶数的元素
            private static void LinqQuery()
            {
                // 初始化查询的数据
                List<string> collection = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    collection.Add("A" + i.ToString());
                }
    
                // 创建查询表达式来获得序号为偶数的元素
                var queryResults = from s in collection
                                   let index = int.Parse(s.Substring(1))
                                   where index % 2 == 0
                                   select s;
                // 输出查询结果
                foreach (string s in queryResults)
                {
                    Console.WriteLine(s);
                }
            }
            #endregion
    复制代码

    从上面的两个方法比较中可以看出使用Linq对集合进行查询时确实简单了许多,并且也容易添加筛选条件(只需要在Where 后面添加额外的筛选条件即可),运行结果当然也是我们期望的,下面也附上下运行结果截图:

     

     2.2 查询XML文件

    之前我们大部分都会使用XPath来对XML文件进行查询,然而使用XPath来查询XML文件需要首先知道XML文件的具体结构,而Linq 查询表达式在查询XML数据的时,可以不需要知道XML文件结构,并且编码更加简单,容易添加判断的条件,下面就具体代码来说明使用Linq查询的好处(这里假设一个场景——有一个定义Persons的XML文件,现在我们要求查找出XML文件中Name节点为“李四”的元素):

    复制代码
    static void Main(string[] args)
            {
                #region Linq to XML 对比
                Console.WriteLine("使用XPath来对XML文件查询,查询结果为:");
                OldLinqToXMLQuery();
                Console.WriteLine("使用Linq方法来对XML文件查询,查询结果为:");
                UsingLinqLinqtoXMLQuery();
                Console.ReadKey();
                #endregion
            }  
     
            #region Linq to XML 对比
        
            // 初始化XML数据
            private static string xmlString = 
                "<Persons>"+
                "<Person Id='1'>"+
                "<Name>张三</Name>"+
                "<Age>18</Age>"+
                "</Person>" +
                "<Person Id='2'>"+
                "<Name>李四</Name>"+
                "<Age>19</Age>"+
                "</Person>"+
                 "<Person Id='3'>" +
                "<Name>王五</Name>" +
                "<Age>22</Age>" +
                "</Person>"+
                "</Persons>";
    
            // 使用XPath方式来对XML文件进行查询
            private static void OldLinqToXMLQuery()
            {
                // 导入XML文件
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(xmlString);
    
                // 创建查询XML文件的XPath
                string xPath = "/Persons/Person";
    
                // 查询Person元素
                XmlNodeList querynodes = xmlDoc.SelectNodes(xPath);
                foreach (XmlNode node in querynodes)
                {
                    // 查询名字为李四的元素
                    foreach (XmlNode childnode in node.ChildNodes)
                    {
                        if (childnode.InnerXml == "李四")
                        {
                            Console.WriteLine("姓名为: "+childnode.InnerXml + "  Id 为:" + node.Attributes["Id"].Value);
                        }
                    }
                }
    
            }
    
            // 使用Linq 来对XML文件进行查询
            private static void UsingLinqLinqtoXMLQuery()
            {
                // 导入XML
                XElement xmlDoc = XElement.Parse(xmlString);
    
                // 创建查询,获取姓名为“李四”的元素
                var queryResults = from element in xmlDoc.Elements("Person")
                                   where element.Element("Name").Value == "李四"
                                   select element;
               
                // 输出查询结果
                foreach (var xele in queryResults)
                {
                    Console.WriteLine("姓名为: " + xele.Element("Name").Value + "  Id 为:" + xele.Attribute("Id").Value);
                }
            }
            #endregion
    复制代码

    使用XPath方式来查询XML文件时,首先需要知道XML文件的具体结构(代码中需要指定XPath为"/Persons/Person", 这就说明必须知道XML的组成结构了),然而使用Linq方式却不需要知道XML文档结构,并且从代码书写的量上也可以看出使用Linq方式的简洁性,下面附上运行结果截图:

    对于Linq to SQL 和Linq to DataSet的例子,我这里就不一一给出了,从上面的两个例子已经完全可以说明使用Linq的好处了,下面总结我理解的好处有:

    • Linq 查询表达式使用上更加简单,而且也易于理解(没有接触过Linq的人也可以大致猜出代码的意图是什么的)
    • Linq 提供了更多的功能,我们可以查询、排序、分组、增加和删除等操作数据的大部分功能
    • 可以使用Linq处理多种数据源,也可以为特定的数据源定义自己的Linq实现(这点将会在深入理解Linq中与大家相信介绍)

    三、Linq的实际操作例子——使用Linq遍历文件目录

     通过前面两部分大家大致可以知道Linq的强大了吧,这部分就具体给出一个例子来看看使用Linq具体可以做些什么事情的? 如果大家做一个文件管理系统的时候,大家都需要遍历文件目录的吧,下面就使用Linq来查找在文件目录中的是否存在特定的文件,具体代码如下:

    复制代码
       static void Main(string[] args)
            {
                string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    
                //FileQuery2(desktop);
                if (!string.IsNullOrEmpty(FileQuery()))
                {
                    Console.WriteLine(FileQuery());
                }
                else
                {
                    Console.WriteLine("电脑桌面上不存在text.txt文件");
                }
                Console.Read();
            }
                // 使用Linq查询
            // 查询桌面是否存在text.txt文件
            private static string FileQuery()
            {
                string desktopdir = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                
                // 获得指定目录和子目录中的文件名
                string[] filenames = Directory.GetFiles(desktopdir, "*.*", SearchOption.AllDirectories);
                List<FileInfo> files = new List<FileInfo>();
                foreach (var filename in filenames)
                {
                    files.Add(new FileInfo(filename));
                }
    
                var results = from file in files
                              where file.Name == "text.txt"
                              select file;
    
                // 输出查询结果
                StringBuilder queryResult = new StringBuilder();
                foreach (var result in results)
                {
                    queryResult.AppendLine("文件的路径为: " + result.FullName);
                }
    
                return queryResult.ToString();
            }
    
            /// <summary>
            /// 使用递归来查找文件
            ///  查询桌面是否存在text.txt文件
            /// </summary>
            private static void FileQuery2(string path)
            {
                // 获得指定目录中的文件(包含子目录)
                string[] filenames = Directory.GetFiles(path);
                List<FileInfo> files = new List<FileInfo>();
                foreach (var filename in filenames)
                {
                    files.Add(new FileInfo(filename));
                }
    
                var results = from file in files
                              where file.Name == "text.txt"
                              select file;
    
                // 输出查询结果
                StringBuilder queryResult = new StringBuilder();
                foreach (var result in results)
                {
                    Console.WriteLine("文件的路径为: " + result.FullName);
                }
    
                // 获得所有子目录
                string[] dirs = Directory.GetDirectories(path);
                if (dirs.Length > 0)
                {
                    foreach (string dir in dirs)
                    {
                        FileQuery2(dir);
                    }
                }
            }
    复制代码

    运行结果为:

     

     我的电脑桌面文件结果为:

     Desttop文件夹
        text.txt
        mytext文件夹
          text文件夹
                text.txt
            text.txt     

    四、小结

     到这里本专题的内容就介绍完了, 本专题主要和大家简单分享了下我对Linq的认识,希望让大家对Linq有个大概的认识,在后面的深入理解Linq系列中将会和大家一起剖析下Linq的实现原理。并且这个专题也是C# 3特性中的最后一个特性的介绍了,在后面一个专题中将带来C# 4中一个最重要的特性——动态类型(dynamic )的引入

     专题中的源码: http://files.cnblogs.com/zhili/LinqDemo.zip

  • 相关阅读:
    Java实现 LeetCode 394 字符串解码
    Java实现 LeetCode 394 字符串解码
    Java实现 LeetCode 392 判断子序列
    Java实现 LeetCode 392 判断子序列
    Java实现 LeetCode 392 判断子序列
    Java实现 LeetCode 391 完美矩形
    Java实现 LeetCode 391 完美矩形
    Java实现 LeetCode 391 完美矩形
    Java实现 LeetCode 390 消除游戏
    Java实现 LeetCode 390 消除游戏
  • 原文地址:https://www.cnblogs.com/varorbc/p/4303177.html
Copyright © 2011-2022 走看看