c# Linq常用的小技巧

2020-07-03 12:01:28王旭

这么看感觉便捷性不太明显是吧~~ 没事,万丈高楼平地起,咋们循行渐进~

获取存在子科室的科室集合

 //2、获取存在子科室的科室集合 1、2
   List<DepartmentDto> existsParentDepartmentIdLst1 = lstDepartItems
    .Where(p => lstDepartItems.Select(k => k.ParentId).Contains(p.Id))
    .ToList();

这里通过引用了外部的集合对象进行关联,在Where内对子科室的ParentId字段与当前集合的科室Id校验,从而得到已存在子科室的科室集合。如果不使用Linq则自己需要写两个循环才能搞定。
如下:

 List<DepartmentDto> existsParentDepartmentIdLst1_1 = new List<DepartmentDto>();
 foreach (DepartmentDto parentDepart in lstDepartItems)
 {
  foreach (DepartmentDto childDepart in lstDepartItems) 
  {
   if (parentDepart.Id == childDepart.ParentId)
   {
     existsParentDepartmentIdLst1_1.Add(parentDepart);
     continue;
   }
  }
 }

这么看,Linq带来的便捷性是否足够明显了,代码优雅了太多了~

科室根据地址分组,获取科室总数、科室平均数

 var groupDto = lstDepartItems
    .GroupBy(p => p.Address)
    .Select(p => new
    {
     Address = p.Key,
     SumEmployeeCount = p.Sum(p => p.EmployeeNumber),
     AvgEmployeeCount = p.Average(p => p.EmployeeNumber),
    }).ToList();

获取两个集合不相等的元素

引用类型的比较处理

这里需要留意我们的科室对象是class,class在C#里属于引用类型。引用类型的比较和值类型的比较大不同相同!引用类型的比较是比较对象在内存堆里指向的地址,并非对象包含的属性值 但是我们预期的比较就是单纯的对值进行比较,所以这里需要通过实现IEqualityComparer<T>接口来对两个引用类型集合对象进行比较。

创建IEqualityComparer<DepartmentDto>对象

 public class DepartmentEqualityComparer : IEqualityComparer<DepartmentDto>
 {
  public bool Equals([AllowNull] DepartmentDto x, [AllowNull] DepartmentDto y)
  {
   // 这里可以写比较的关键代码~
   return x.Id == y.Id;
  }

  public int GetHashCode([DisallowNull] DepartmentDto obj)
  {
   return obj.ToString().GetHashCode();
  }
 }

接下来,定义一个新的集合,再手动向这个集合追加元素。

 List<DepartmentDto> lstDepartItemsCPs = InitDepartmentData();
   lstDepartItemsCPs.Add(new DepartmentDto()
   {
    Address = "三马路XX号",
    Id = 6,
    Name = "二级三号科室",
    Remark = "",
    TelPhone = "0731-6222222",
    EmployeeNumber = 7
   });

集合比较代码:

// 这里如果DepartmentDto为引用类型(class)则需要使用比较器DepartmentEqualityComparer才能返回我们的预期值(根据ID值判断是否相等)
   List<DepartmentDto> diffList = lstDepartItemsCPs.Except(lstDepartItems, new DepartmentEqualityComparer()).ToList();
   // 获取相等元素
   List<DepartmentDto> diffList1 = lstDepartItemsCPs.Intersect(lstDepartItems.Select(p => p), new DepartmentEqualityComparer()).ToList();
  // 需要添加IEqualityComparer,因为集合内的内容为引用类型!所以两个集合的“值”是不同的,引用类型的值在这里还包含了指向的内存堆的引用地址
   bool isEqual = lstDepartItems.SequenceEqual(InitDepartmentData(), new DepartmentEqualityComparer());