17 C# 第十五章 Linq标准查询的使用

这里主要收集了一些查询表达式的基本用法,例子短小,方便以后参考使用。


1, 查询表达式概述


什么是查询表达式, 还是以一个实际的例子来描述一下。
例子中会把它和查询运算符加以区分。


实例1:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Linq_2_Test
{
    class Program
    {
        public class Student
        {
            public string First { get; set; }
            public string Last { get; set; }
            public int ID { get; set; }
            public List<int> Scores;
        }

        // Create a data source by using a collection initializer.
        static List<Student> students = new List<Student>
        {
           new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 92, 81, 60}},
           new Student {First="Claire",   Last="O’Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}},
           new Student {First="Sven",     Last="Mortensen", ID=113, Scores= new List<int> {88, 94, 65, 91}},
           new Student {First="Cesar",    Last="Garcia", ID=114, Scores= new List<int> {97, 89, 85, 82}},
           new Student {First="Debra",    Last="Garcia", ID=115, Scores= new List<int> {35, 72, 91, 70}},
           new Student {First="Fadi",     Last="Fakhouri", ID=116, Scores= new List<int> {99, 86, 90, 94}},
           new Student {First="Hanying",  Last="Feng", ID=117, Scores= new List<int> {93, 92, 80, 87}},
           new Student {First="Hugo",     Last="Garcia", ID=118, Scores= new List<int> {92, 90, 83, 78}},
           new Student {First="Lance",    Last="Tucker", ID=119, Scores= new List<int> {68, 79, 88, 92}},
           new Student {First="Terry",    Last="Adams", ID=120, Scores= new List<int> {99, 82, 81, 79}},
           new Student {First="Eugene",   Last="Zabokritski", ID=121, Scores= new List<int> {96, 85, 91, 60}},
           new Student {First="Michael",  Last="Tucker", ID=122, Scores= new List<int> {94, 92, 91, 91} }
        };

        static void Main(string[] args)
        {
            // Create the query.
            // The first line could also be written as "var studentQuery ="
            Console.WriteLine("================  Using LinQ Expression  ================");
            IEnumerable<Student> studentQuery1 =
                from student in students
                where student.Scores[0] > 90 && student.Scores[3] < 80
                orderby student.Scores[0] descending
                select student;

            foreach (Student item in studentQuery1)
            {
                Console.WriteLine("Name: {0}  :    {1}", item.Last, item.Scores[0]);
            }

            Console.WriteLine("");
            Console.WriteLine("================  Using LinQ Function  ================");
            IEnumerable<Student> studentQuery2 = students.Where(
                    student => student.Scores[0] > 90 && student.Scores[3] < 80
                );

            foreach (Student item in studentQuery2)
            {
                Console.WriteLine("Name: {0}  :    {1}", item.Last, item.Scores[0]);
            }

            Console.ReadKey();
        }
    }
}

比较代码中查询表达式和查询运算符,可以看出查询表达式相对比较容易理解。它的风格更类似与SQL,估计这也是让人觉得熟悉和相对好理解的原因。

查询表达式一般以 "from" 作为开始,以一个 "select" 或 "group" 来结束。中间用"where" 来标识我们的查询条件。



2, 特点及实例:

投射: 关键字 select

      使用表达式来查询一个特定类型时,结果并非一定是原始类型。
      select表达式允许将数据投射成一个完全不同的数据类型。

实例2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace case1_select_sample
{
    class Program
    {
        static void ListFiles(string strRootDir, string strSearchPattern)
        {
            // 这里Directory.GetFiles(strRootDir, strSearchPattern)的返回值为 string[]
            // 但使用selece操作把它映射到了一个新创建的 FileInfo 对象中。
            Console.WriteLine("===  使用select把查询结果投射到不同于原数据的数据类型  ===");
            IEnumerable<FileInfo> files =
                from fileName in Directory.GetFiles(strRootDir, strSearchPattern)
                select new FileInfo(fileName);

            foreach(FileInfo file in files)
            {
                Console.WriteLine(".{0} ({1})", file.Name, file.LastWriteTime);
            }

            Console.WriteLine("");
            Console.WriteLine("===  使用select把查询结果投射到匿名类型  ===");
            // 这里Directory.GetFiles(strRootDir, strSearchPattern)的返回值为 string[]
            // 这里使用selece操作把它映射到了一个新创建的匿名对象中。
            var varfiles =
                from fileName in Directory.GetFiles(strRootDir, strSearchPattern)
                select new 
                {
                    Name = fileName,
                    LastWriteTime = File.GetLastWriteTime(fileName)
                };

            foreach (var vfile in varfiles)
            {
                Console.WriteLine(".{0} ({1})", vfile.Name, vfile.LastWriteTime);
            }
        }

        static void Main(string[] args)
        {
            ListFiles("D:\\testdir\\CSharpTest\\Essential\\chapter_16\\Linq_2_Test\\case1_select_sample", "*.cs");

            Console.ReadKey();
        }
    }
}


测试结果:

select_map_diam


投射到匿名类型的优点:如果我们检索出的数据量不大,使用匿名类型并没有太大的优势,假如检索的数据量非常大时,
匿名类型可以帮助我们直接投射出我们希望得到的数据,会大大减少无用数据对系统资源的占用。


筛选: 关键字 where

      使用某些限制条件对我们所需要的数据进行过滤。

排序: 关键字 orderby
这两个相对简单,在  实例1 中都有涉及。




let 子句: 用来避免多余化的实例。
什么是多余化的实例,还是用程序来说明吧。


实例3:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace case2_let_sample
{
    class Program
    {
        static void ListFiles(string strRootDir, string strSearchPattern)
        {
            // 注意这里使用了2次new操作符,创建了2个FileInfo对象。
            // 因为我们想使用FileInfo中的length来对结果进行排序,又想把它投射到一个新对象中。
            // 虽然对程序没什么影响,但实在是浪费,
            IEnumerable<FileInfo> files =
                from fileName in Directory.GetFiles(strRootDir, strSearchPattern)
                orderby new FileInfo(fileName).Length, fileName
                select new FileInfo(fileName);

            foreach (FileInfo file in files)
            {
                Console.WriteLine(".{0} ({1})", file.Name, file.LastWriteTime);
            }

            Console.WriteLine("");
            Console.WriteLine("======   Use Let 避免多余实例化 ... ...   ======");
            // 这里只创建了一个FileInfo对象,并使用let子句进行赋值,在下面的语句中就可以
            // 一直使用这个对象了。
            IEnumerable<FileInfo> letfiles =
                from fileName in Directory.GetFiles(strRootDir, strSearchPattern)
                let file = new FileInfo(fileName)
                orderby file.Length, fileName
                select file;

            foreach (FileInfo file in letfiles)
            {
                Console.WriteLine(".{0} ({1})", file.Name, file.LastWriteTime);
            }
        }

        static void Main(string[] args)
        {
            ListFiles("D:\\testdir\\CSharpTest\\Essential\\chapter_16\\Linq_2_Test\\case1_select_sample", "*.*");

            Console.ReadKey();
        }
    }
}


分组:  关键字 group ... by 和 IGrouping<TKey, TElement>

       不用多说了就是把数据按某种方式归类。
       
        TKey: 简单的理解就是分组时使用的关键字,或者是某种划分的条件。
        TElement: 就是分组后小组内包含的元素

这里个例子中先会遍历 整个集合的Group,然后在遍历Group中的元素。
实例4:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace case3_group_sample
{
    class Program
    {
        public class Student
        {
            public string First { get; set; }
            public string Last { get; set; }
            public int ID { get; set; }
            public List<int> Scores;
        }

        // Create a data source by using a collection initializer.
        static List<Student> students = new List<Student>
        {
           new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 92, 81, 60}},
           new Student {First="Claire",   Last="O’Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}},
           new Student {First="Sven",     Last="Mortensen", ID=113, Scores= new List<int> {88, 94, 65, 91}},
           new Student {First="Cesar",    Last="Garcia", ID=114, Scores= new List<int> {97, 89, 85, 82}},
           new Student {First="Debra",    Last="Garcia", ID=115, Scores= new List<int> {35, 72, 91, 70}},
           new Student {First="Fadi",     Last="Fakhouri", ID=116, Scores= new List<int> {99, 86, 90, 94}},
           new Student {First="Hanying",  Last="Feng", ID=117, Scores= new List<int> {93, 92, 80, 87}},
           new Student {First="Hugo",     Last="Garcia", ID=118, Scores= new List<int> {92, 90, 83, 78}},
           new Student {First="Lance",    Last="Tucker", ID=119, Scores= new List<int> {68, 79, 88, 92}},
           new Student {First="Terry",    Last="Adams", ID=120, Scores= new List<int> {99, 82, 81, 79}},
           new Student {First="Eugene",   Last="Zabokritski", ID=121, Scores= new List<int> {96, 85, 91, 60}},
           new Student {First="Michael",  Last="Tucker", ID=122, Scores= new List<int> {94, 92, 91, 91} }
        };

        static void Main(string[] args)
        {
            IEnumerable<IGrouping<bool, Student>> studentQuery1 =
                from student in students
                group student by student.Scores[0] > 80;

            foreach (IGrouping<bool, Student> item in studentQuery1)
            {
                Console.WriteLine("=========  ==============  =========");
                foreach(Student stu in item)
                {
                    Console.WriteLine("{0}:  {1}", stu.First, stu.Scores[0]);
                }
            }
            Console.ReadKey();
        }
    }
}



       程序中的分组的条件是分数大于80的为一组,小于80的为一组,这里的"大于80"其实是一个bool型
       所以 TKey就是bool,分组后小组保存的元素是还是学生的信息,所以 TElement 就是 Student。


测试结果:
group_by_result_diam




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值