linq to objects 查询表达式

首先定义数据源

//学生类
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public int classId { get; set; }

    public static List<Student> GetStudent()
    {
         return new List<Student>() {
             new Student() { Id = 1000, Name = "张三", Age = 25,,classId=1},
             new Student() { Id = 1002, Name = "李四", Age = 18,classId=2 },
             new Student() { Id = 1004, Name = "王五", Age = 18, classId=2 },
             new Student() { Id = 1006, Name = "赵六", Age = 12,classId=1}
          };
     }
}
//班级类
public class Classes
{
    public int Id { get; set; }
    public string Name { get; set; }

    public static List<Classes> GetClasses()
    {
        return new List<Classes>() {
            new Classes() { Id = 1, Name = "软件工程"},
            new Classes() { Id = 2, Name = "计算机" }
        };
    }
 }

【1】where子句 过滤
查询表达式:


var query = from p in Student.GetStudent()
            where p.Age < 18
            select p;

点标记:

var query = Student.GetStudent().Where(p => p.Age < 18).Select(p => p);

点标记的select可以去掉,查询表达式中的p称为范围变量
Cast、OfType和显式类型的变量
linq不能处理ArrayList或者object[] 的查询,但可以使用Cast、OfType来解决这个问题,Cast通过把每个元素都转换成目标类型(遇到不是正确类型的任何元素的时候,就会出错)来处理,而OfType首先进行一个测试,以跳过任何具有错误类型的元素。

ArrayList list = new ArrayList { "a","b","c"};
IEnumerable<string> strings = list.Cast<string>();
foreach (var item in strings)
{
    Console.WriteLine(item);
}
list = new ArrayList { 5, 8, 's', "dd" };
IEnumerable<int> ints = list.OfType<int>();
foreach (var item in ints)
{
   Console.WriteLine(item);
}

使用显示类型的范围变量来自动调用Cast

ArrayList list = new ArrayList { "abcdef","bcde","cdef"};
var query = from string p in list
            select p.Substring(0, 3);

【2】orderby子句 排序
查询表达式:

var query = from p in Student.GetStudent()
            orderby p.Age ascending,p.Id descending
            select p;

点标记:

var query = Student.GetStudent().OrderBy(p => p.Age).ThenByDescending(p => p.Id);

【3】let子句 透明标识符

var result = from p in Student.GetStudent()
             //透明标识符 let , 避免了计算两次姓名的字符数
             let length = p.Name.Length
             orderby length
             select new { Name=p.Name ,Length=length };
foreach (var item in result)
{
   Console.WriteLine(item.Length  + ":" + item.Name);
}

【4】join子句 内链接
查询表达式:

 var query = from p in Student.GetStudent()
             join q in Classes.GetClasses()
             on p.classId equals q.Id
             select new { ClassName=q.Name,StudentName=p.Name};

点标记:

var query = Student.GetStudent().Join(Classes.GetClasses(), p => p.classId, q => q.Id, (p, q) => new { ClassName = q.Name, StudentName = p.Name });

【5】join…into子句 分组连接
查询表达式:

var query = from p in Classes.GetClasses()
            join q in Student.GetStudent()
            on p.Id equals q.classId into groupedStudent
            select new {studentCount = groupedStudent.Count(), classes = p };
foreach (var item in query)
{
     Console.WriteLine($"班级:{item.classes.Name},学生数量:{item.studentCount}");
}

点标记:

var query = Classes.GetClasses().GroupJoin(Student.GetStudent(), p => p.Id, q => q.classId, (p, q) => new { studentCount = q.Count(), classes = p });

【6】from子句 交叉连接和合并序列
查询表达式:

var query = from p in Student.GetStudent()
            from q in Classes.GetClasses()
            select new { student = p, classes = q };
foreach (var item in query)
{
    Console.WriteLine($"学生姓名:{item.student.Name}   班级:{item.classes.Name}");
}
运行结果:
学生姓名:张三   班级:软件工程
学生姓名:张三   班级:计算机
学生姓名:李四   班级:软件工程
学生姓名:李四   班级:计算机
学生姓名:王五   班级:软件工程
学生姓名:王五   班级:计算机
学生姓名:赵六   班级:软件工程
学生姓名:赵六   班级:计算机

点标识:

var query = Student.GetStudent().SelectMany(p => Classes.GetClasses(), (p, q) => new { student = p, classes = q });
foreach (var item in query)
{
   Console.WriteLine($"学生姓名:{item.student.Name}   班级:{item.classes.Name}");
}

【7】group…by子句 分组
查询表达式:

var query = from p in Student.GetStudent()
             group p by p.Age;
foreach (var item in query)
{
     Console.WriteLine($"{item.Key}岁的学生数量:{item.Count()}");
}

点标记:

var query = Student.GetStudent().GroupBy(p => p.Age);
foreach (var item in query)
{
    Console.WriteLine($"{item.Key}岁的学生数量:{item.Count()}");
}

【8】查询延续
把表达式的结果用作另外一个查询表达式的初始序列 上下文关键字into 并作为新的范围变量提供一个名称,上一个表达式的范围变量将不能再使用。
查询表达式:

 var query = from p in Student.GetStudent()
             group p by p.Age into grouped
             select new { Age=grouped.Key,Count=grouped.Count()};
foreach (var item in query)
{
      Console.WriteLine($"{item.Age}岁的学生数量:{item.Count}");
}

点标记:

var query = Student.GetStudent().GroupBy(p => p.Age).Select(grouped => new { Age = grouped.Key, Count = grouped.Count() });
foreach (var item in query)
{
      Console.WriteLine($"{item.Age}岁的学生数量:{item.Count}");
}

但join…into 不是延续 join..into可以使用所有的早期的范围变量,延续会清除之前的范围变量,只有在延续中声明的范围变量才能在供后续使用。

总结:所有的查询表达式都可以转换成点标记的形式,但所有的点标记不一定可以转换成查询表达式,例如点标记的Reverse、ToDictionary就没有对应的查询表达式,至于查询表达式与点标记如何选择,就看你自己的编码习惯了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值