这里主要收集了一些查询表达式的基本用法,例子短小,方便以后参考使用。
什么是查询表达式, 还是以一个实际的例子来描述一下。
例子中会把它和查询运算符加以区分。
实例1:
比较代码中查询表达式和查询运算符,可以看出查询表达式相对比较容易理解。它的风格更类似与SQL,估计这也是让人觉得熟悉和相对好理解的原因。
查询表达式一般以 "from" 作为开始,以一个 "select" 或 "group" 来结束。中间用"where" 来标识我们的查询条件。
select表达式允许将数据投射成一个完全不同的数据类型。
实例2:
匿名类型可以帮助我们直接投射出我们希望得到的数据,会大大减少无用数据对系统资源的占用。
排序: 关键字 orderby
这两个相对简单,在 实例1 中都有涉及。
let 子句: 用来避免多余化的实例。
什么是多余化的实例,还是用程序来说明吧。
实例3:
TKey: 简单的理解就是分组时使用的关键字,或者是某种划分的条件。
TElement: 就是分组后小组内包含的元素
这里个例子中先会遍历 整个集合的Group,然后在遍历Group中的元素。
实例4:
所以 TKey就是bool,分组后小组保存的元素是还是学生的信息,所以 TElement 就是 Student。
测试结果:
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();
}
}
}
测试结果:
匿名类型可以帮助我们直接投射出我们希望得到的数据,会大大减少无用数据对系统资源的占用。
筛选: 关键字 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();
}
}
}
所以 TKey就是bool,分组后小组保存的元素是还是学生的信息,所以 TElement 就是 Student。
测试结果: