最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# Linq常用的小技巧

 更新時間:2020年07月03日 10:34:22   作者:長沙大鵬  
這篇文章主要介紹了c# Linq常用的小技巧,文中講解非常詳細,示例代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下

前言

在C#語言發(fā)展的歷史長河中,Linq是一個極其重要的里程碑!

Linq的語法吸取了SQL語法的特性,同時配合Lambda表達式又可以使代碼更加優(yōu)雅!
可以這么說,用好了Linq可以大大提高程序猿的工作效率,畢竟我們的日常工作本質(zhì)就是對數(shù)據(jù)的處理。經(jīng)歷了十多年的發(fā)展,現(xiàn)在微軟自帶的內(nèi)庫包含的Linq函數(shù)已經(jīng)非常多了,幾乎滿足我們?nèi)粘9ぷ鳌?/p>

下面根據(jù)一個對科室數(shù)據(jù)操作的例子,就個人覺得日常高頻使用的Linq小技巧貼出來,權當是做個筆記了。

初始化數(shù)據(jù)

定義模型

這里定義一個科室對象,模擬我們?nèi)粘9ぷ鞯目剖倚畔???剖掖嬖趯蛹夑P系,還有一個員工數(shù)量的屬性。模型如下:

 public class DepartmentDto
 {
  public int Id { get; set; }   

  public int? ParentId { get; set; }

  public string Name { get; set; }

  public string TelPhone { get; set; }
 
  public string Address { get; set; }

  public string Remark { get; set; }
   
  public int EmployeeNumber { get; set; }
 }

初始化數(shù)據(jù)

  public List<DepartmentDto> InitDepartmentData()
  {
   List<DepartmentDto> lst = new List<DepartmentDto>();
   lst.AddRange(new DepartmentDto[] {
    new DepartmentDto() {
      Address ="一馬路XX號",
      Id=1,
      Name="一級一號科室",
      Remark="",
      TelPhone="0731-6111111",
      EmployeeNumber=3,
    },
    new DepartmentDto() {
      Address ="二馬路XX號",
      Id=2,
      Name="一級二號科室",
      Remark="",
      TelPhone="0731-6111111",
      EmployeeNumber=4,
    },
    new DepartmentDto() {
      Address ="三馬路XX號",
      Id=3,
      Name="一級三號科室",
      Remark="",
      TelPhone="0731-6222222",
      EmployeeNumber=6,
    },
    new DepartmentDto() {
      Address ="一馬路XX號",
      ParentId=1,
      Id=4,
      Name="二級一號科室",
      Remark="",
      TelPhone="0731-6222222",
      EmployeeNumber=7,
    },
    new DepartmentDto() {
      Address ="二馬路XX號",
      ParentId=2,
      Id=5,
      Name="二級二號科室",
      Remark="",
      TelPhone="0731-6222222",
      EmployeeNumber=5,
    },
   });
   return lst;
  }

獲取未存在父級科室的科室集合

 List<DepartmentDto> lstDepartItems = InitDepartmentData();
   //1、獲取未存在父級科室的科室集合 1、2、3   
   List<DepartmentDto> notExistsParentDepartmentIdLst = lstDepartItems
    .Where(p => !p.ParentId.HasValue)
    .ToList();

這里比較簡單,Where內(nèi)校驗下ParentId的值為空即可,不使用Linq則需要自己手寫一個循環(huán)搞定,如下:

 List<DepartmentDto> notExistsParentDepartmentIdLst_1 = new List<DepartmentDto>();
 foreach (DepartmentDto department in lstDepartItems)
 {
   if (!department.ParentId.HasValue)
    notExistsParentDepartmentIdLst_1.Add(department);
 }

這么看感覺便捷性不太明顯是吧~~ 沒事,萬丈高樓平地起,咋們循行漸進~

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

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

這里通過引用了外部的集合對象進行關聯(lián),在Where內(nèi)對子科室的ParentId字段與當前集合的科室Id校驗,從而得到已存在子科室的科室集合。如果不使用Linq則自己需要寫兩個循環(huán)才能搞定。
如下:

 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帶來的便捷性是否足夠明顯了,代碼優(yōu)雅了太多了~

科室根據(jù)地址分組,獲取科室總數(shù)、科室平均數(shù)

 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#里屬于引用類型。引用類型的比較和值類型的比較大不同相同!引用類型的比較是比較對象在內(nèi)存堆里指向的地址,并非對象包含的屬性值 但是我們預期的比較就是單純的對值進行比較,所以這里需要通過實現(xiàn)IEqualityComparer<T>接口來對兩個引用類型集合對象進行比較。

創(chuàng)建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才能返回我們的預期值(根據(jù)ID值判斷是否相等)
   List<DepartmentDto> diffList = lstDepartItemsCPs.Except(lstDepartItems, new DepartmentEqualityComparer()).ToList();
   // 獲取相等元素
   List<DepartmentDto> diffList1 = lstDepartItemsCPs.Intersect(lstDepartItems.Select(p => p), new DepartmentEqualityComparer()).ToList();
  // 需要添加IEqualityComparer,因為集合內(nèi)的內(nèi)容為引用類型!所以兩個集合的“值”是不同的,引用類型的值在這里還包含了指向的內(nèi)存堆的引用地址
   bool isEqual = lstDepartItems.SequenceEqual(InitDepartmentData(), new DepartmentEqualityComparer());

值類型的比較處理

可能你覺得需要去創(chuàng)建IEqualityComparer<DepartmentDto>對象過于麻煩,那么想下是否一定需要將科室對象的類型設定為class,是否有更合適的類型可以替換? 答案是有的,微軟推薦如果對具體模型不需要多次執(zhí)行裝箱、拆箱操作最好將模型設置為結構struct而非class。 現(xiàn)在我們回過頭將科室對象的類型更新為struct

然后發(fā)現(xiàn)上面集合比較的代碼可以簡化成這樣:

 // 這里如果DepartmentDto為值類型(struct)則不需要使用比較器DepartmentEqualityComparer即可返回我們的預期值(根據(jù)ID值判斷是否相等)
   List<DepartmentDto> diffList3 = lstDepartItemsCPs.Except(lstDepartItems).ToList();
   // 獲取相等元素
   List<DepartmentDto> diffList4 = lstDepartItemsCPs.Intersect(lstDepartItems.Select(p => p)).ToList();
     // 如果把DepartmentDto的類型改為值類型則可以不需要IEqualityComparer進行判斷的結果也會為true
   isEqual = lstDepartItems.SequenceEqual(InitDepartmentData());

OfType和Cast的不同之處

OfType允許對集合的項進行隱性轉換(非強轉Convert)且在轉換前會進行判斷,當類型不允許轉換則continue到下一個集合項。而Cast則是子項不進行判斷,直接隱性轉換,所以理論上效率更高,當然相對的出錯率也更高~

  public void ConvertListTest()
  {
   try
   {
    object[] ss = { 1, "2", 3, "四", "五", "7" };
    // 1、3 OfType的本質(zhì)是循環(huán)集合,對每個集合項進行類型驗證(不是強轉,所以此處的結果是1、3 而不是1、2、3、7)
    var lst = ss.ToList().OfType<int>().ToList();
    // 3 
    int max = ss.OfType<int>().Max();
    // 這句代碼會提示“System.InvalidCastException:“Unable to cast object of type 'System.String' to type 'System.Int32'.”異常,原因:Cast的執(zhí)行效率會略高與OfType,因為在對集合項進行類型轉換前不會對其進行類型校驗,當你確保集合的類型是安全的則可以用Cast,但是能用到Cast和OfType的時候基本上都是用OfType了..
    int maxCast = ss.Cast<int>().Max();
   }
   catch (Exception ex)
   {
    Console.WriteLine(ex);
   }
  }

上述代碼已上傳到github,地址: https://github.com/QQ897878763/LinqStudySample.git

以上就是c# Linq常用的小技巧的詳細內(nèi)容,更多關于c# Linq小技巧的資料請關注腳本之家其它相關文章!

相關文章

  • C# FileStream復制大文件

    C# FileStream復制大文件

    這篇文章主要為大家詳細介紹了C# FileStream復制大文件的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C#連接Oracle的方法實例總結

    C#連接Oracle的方法實例總結

    這篇文章主要介紹了C#連接Oracle的方法,結合實例形式總結分析了幾種常見的C#連接Oracle數(shù)據(jù)庫的操作技巧與相關注意事項,需要的朋友可以參考下
    2017-06-06
  • C#中如何執(zhí)行存儲過程方法

    C#中如何執(zhí)行存儲過程方法

    C#中如何執(zhí)行存儲過程方法,需要的朋友可以參考一下
    2013-04-04
  • c# 獲取字符串的字節(jié)數(shù)的方法

    c# 獲取字符串的字節(jié)數(shù)的方法

    本篇文章主要是對c#中獲取字符串的字節(jié)數(shù)的方法進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 配置C#的系統(tǒng)環(huán)境變量的方法

    配置C#的系統(tǒng)環(huán)境變量的方法

    配置C#的系統(tǒng)環(huán)境變量的方法...
    2007-03-03
  • C#實現(xiàn)循環(huán)發(fā)送電腦屏幕截圖

    C#實現(xiàn)循環(huán)發(fā)送電腦屏幕截圖

    這篇文章主要為大家詳細介紹了C#實現(xiàn)循環(huán)發(fā)送電腦屏幕截圖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C#中yield return用法分析

    C#中yield return用法分析

    這篇文章主要介紹了C#中yield return用法,對比使用yield return與不使用yield return的流程,更直觀的分析了yield return的用法,需要的朋友可以參考下
    2014-09-09
  • C# 調(diào)用C++寫的dll的實現(xiàn)方法

    C# 調(diào)用C++寫的dll的實現(xiàn)方法

    C#調(diào)用C++的非托管類的dll其實很簡單基本就是固定的調(diào)用格式,有需要的朋友可以參考一下
    2013-10-10
  • 詳解C#如何使用消息隊列MSMQ

    詳解C#如何使用消息隊列MSMQ

    消息隊列 (MSMQ Microsoft Message Queuing)是MS提供的服務,也就是Windows操作系統(tǒng)的功能,下面就跟隨小編一起了解一下C#中是如何使用消息隊列MSMQ的吧
    2024-01-01
  • 詳解c# 線程同步

    詳解c# 線程同步

    這篇文章主要介紹了c# 線程同步的相關資料,文中講解非常細致,示例代碼幫助大家更好的理解和學習c# 多線程,感興趣的朋友可以了解下
    2020-07-07

最新評論

徐闻县| 宾阳县| 盐津县| 大安市| 宜阳县| 壤塘县| 沙湾县| 襄城县| 霍邱县| 汤阴县| 分宜县| 来安县| 营山县| 崇阳县| 社旗县| 团风县| 长海县| 乌恰县| 西盟| 马关县| 孟津县| 松桃| 邹平县| 青田县| 固安县| 开江县| 庄河市| 珠海市| 政和县| 正阳县| 清水县| 出国| 城口县| 油尖旺区| 瓦房店市| 理塘县| 龙门县| 汶川县| 高雄县| 肥西县| 岳西县|