1. LINQ的作用
LINQ(语言级集成查询)项目的意图是统一且对称的方式,让程序员在广义的数据上得到或操作“数据”。
1.1 LINQ表达式是强类型和可扩展的
1.2 核心LINQ程序集
程序集 | 描述 |
System.Core.dll | 定义了核心LINQ API类型,System.Linq命名空间在其中。 |
System.Data.Linq.dll | LINQ to SQL |
System.Data.DataSetExtensions.dll | LINQ to DataSet |
System.Xml.Linq.dll | LINQ to XML |
2. LINQ查询表达式
static void myLinq() { int[] intArray = { 1, 2, 3, 5, 10, 8 }; IEnumerable<int> subset = from g in intArray where g > 2 orderby g select g; foreach (int n in subset) { Console.Write("{0} ", n); } }
2.1 LINQ和隐式类型局部变量
static void myLinq() { int[] intArray = { 1, 2, 3, 5, 10, 8 }; var subset = from g in intArray where g > 2 //orderby g select g; foreach (var n in subset) { Console.Write("{0} ", n); } }
2.2 LINQ和扩展方法
System.Array没有直接实现IEnumerable<T>接口,但通过静态的System.Linq.Enumerable类这个类型间接得到该类型所需的功能,还得到了许多其他与LINQ相关的成员。
2.3 延迟执行与立即执行
static void myLinq() { int[] intArray = { 1, 2, 3, 5, 10, 8 }; //延迟执行 IEnumerable<int> subset = from g in intArray where g > 2 orderby g select g; //立即执行,使用ToArray<T>()、ToDictionary<TSource、TKey>()或ToList<T>()等扩展方法以强类型容器来捕获LINQ查询结果。 IEnumerable<int> subset2 = (from g in intArray where g > 2 orderby g select g).ToList<int>(); Console.Write("延迟执行(前):"); foreach (int n in subset) { Console.Write("{0} ", n); } Console.WriteLine(); Console.Write("立即执行(前):"); foreach (int n in subset2) { Console.Write("{0} ", n); } Console.WriteLine(); intArray[0] = 100;//改变数组第一个元素的值 Console.Write("延迟执行(后):"); foreach (int n in subset) { Console.Write("{0} ", n); } Console.WriteLine(); Console.Write("立即执行(后):"); foreach (int n in subset2) { Console.Write("{0} ", n); } }
3. LINQ和泛型表达式
class Student { public string Name = string.Empty; public int Math; public int English; } static void Main(string[] args) { //myLinq(); List<Student> stu = new List<Student>(){ new Student{Name="Dawei",English=89,Math=91}, new Student{Name="Sven",English=93,Math=92} }; //找出两门课成绩都在90分以上的学生 var substu = from t in stu where t.Math > 90 && t.English > 90 select t; foreach (var s in substu) { Console.WriteLine(s.Name); } Console.ReadLine(); }
4. LINQ与非泛型集合
使用OfType<T>()筛选数据。
class Student { public string Name = string.Empty; public int Math; public int English; } static void Main(string[] args) { ArrayList stu=new ArrayList(){ new Student{Name="Dawei",English=89,Math=91}, new Student{Name="Sven",English=93,Math=92}, "1" }; IEnumerable<Student> stulist = stu.OfType<Student>(); //找出两门课成绩都在90分以上的学生 var substu = from t in stulist where t.Math > 90 && t.English > 90 select t; foreach (var s in substu) { Console.WriteLine(s.Name); } Console.ReadLine(); }
5. 查询运算符的内部表示
5.1 使用查询运算符建立查询表达式
5.2 使用IEnumerable类型和Lambda表达式来建立查询表达式
5.3 使用IEnumerable类型和匿名方法来建立查询表达式
5.4 使用IEnumerable类型和原始代理来建立查询表达式
public static bool Filter(Student t) { return t.Math > 90 && t.English > 90; } public static Student order(Student t) { return t; } static void Main(string[] args) { //myLinq(); //LINQ和泛型集合 /* List<Student> stu = new List<Student>(){ new Student{Name="Dawei",English=89,Math=91}, new Student{Name="Sven",English=93,Math=92} }; //找出两门课成绩都在90分以上的学生 var substu = from t in stu where t.Math > 90 && t.English > 90 select t; foreach (var s in substu) { Console.WriteLine(s.Name); } */ ArrayList stu=new ArrayList(){ new Student{Name="Dawei",English=89,Math=91}, new Student{Name="Sven",English=93,Math=92}, "1" }; IEnumerable<Student> stulist = stu.OfType<Student>(); //找出两门课成绩都在90分以上的学生 //1.使用查询运算符建立查询表达式 //var substu = from t in stulist where t.Math > 90 && t.English > 90 select t; //2.使用IEnumerable类型和Lambda表达式来建立查询表达式 //var substu = stulist.Where(t => t.Math > 90 && t.English > 90) // .OrderBy(t => t).Select(t => t); //3.使用IEnumerable类型和匿名方法来建立查询表达式 //Func<Student, bool> SearchFilter = // delegate(Student t) { return t.Math > 90 && t.English > 90; }; //Func<Student, Student> itemOrder = delegate(Student t) { return t; }; //var substu = stulist.Where(SearchFilter).OrderBy(itemOrder).Select(itemOrder); //4.使用IEnumerable类型和原始代理来建立查询表达式 Func<Student, bool> SearchFilter = new Func<Student, bool>(Filter); Func<Student, Student> itemOrder = new Func<Student, Student>(order); var substu = stulist.Where(SearchFilter).OrderBy(itemOrder).Select(itemOrder); foreach (var s in substu) { Console.WriteLine(s.Name); } Console.ReadLine(); }
注意点:1)查询表达式是用各种查询运算符建立的;
2)查询运算符只是调用有System.LINQ.Enumerable定义的扩展方法的简化符号;
3)Enumerable的很多方法要求委托(特别是Fun<>)作为参数;
4)在C#3.0中,任何要求代理参数的方法都可传入一个Lambda表达式;
5)Lambda表达式是伪装的匿名方法(这提高了可读性);
6)匿名方法是对指派一个原始委托然后手工建立一个委托目标方法的简化符号。
6. LINQ运算符
运算符 | 含义 |
from、in | 从容器中提取数据集 |
where | 添加限制条件 |
select | 从容器中选择一个序列 |
join、on、equals、into | 关联操作 |
orderby、ascending、descending | 排序 |
group、by | 分组 |
Reverse<>()、ToArray<>()、ToList<>() | 对结果集进行转换 |
Distinct<>()、Union<>()、Intersect<>() | 对结果集进行集操作 |
Count<>()、Min<>()、Max<>()、Sum<>() | 对结果集进行聚合操作 |
class Student { public string Name = string.Empty; public int Math; public int English; public override string ToString() { return "Name=" + Name + ",Math=" + Math.ToString() + ",English=" + English.ToString(); } } class Program { public static bool Filter(Student t) { return t.Math > 90 && t.English > 90; } public static Student order(Student t) { return t; } static void Main(string[] args) { List<Student> stu = new List<Student>(){ new Student{Name="Dawei",English=89,Math=91}, new Student{Name="Sven",English=93,Math=92}, new Student{Name="King",English=95,Math=96}, new Student{Name="Sven",English=93,Math=92} }; //基本选择 var stus = from t in stu select t; //统计两门课成绩都在90分以上的学生数 var stuCount = (from t in stu select t).Count<Student>(); //投影新数据类型 var stunew = from t in stu select new { t.Name, t.Math }; //逆转结果集 var stusReverse = (from t in stu select t).Reverse<Student>(); //排序 var stuDec = from t in stu orderby t.Math descending select t; //去重复 var stuDiff = (from t in stu select t.Name).Distinct<string>(); foreach (var s in stus) { Console.WriteLine(s.ToString()); } Console.WriteLine("总人数:{0}",stuCount); Console.WriteLine("新数据类型"); foreach (var s in stunew) { Console.WriteLine(s.ToString()); } Console.WriteLine("逆转结果集"); foreach (var s in stusReverse) { Console.WriteLine(s.ToString()); } Console.WriteLine("数学降序排序"); foreach (var s in stuDec) { Console.WriteLine(s.ToString()); } Console.WriteLine("去重复"); foreach (var s in stuDiff) { Console.WriteLine(s); } }
7. LINQ查询
将查询结构转为Array类型(或使用Enumerable类型的其他成员转换为其他合适的容器)返回做处理。
static Array getSubSet() { Student[] stu = new Student[]{ new Student{Name="Dawei",English=89,Math=91}, new Student{Name="Sven",English=93,Math=92}, new Student{Name="King",English=95,Math=96} }; var stunew = from t in stu select new { t.Name, t.Math }; return stunew.ToArray(); } static void Main(string[] args) { Array objs = getSubSet(); foreach (var o in objs) { Console.WriteLine(o.ToString()); } }