C# 基礎知識系列-7 Linq詳解

来源:https://www.cnblogs.com/c7jie/archive/2020/04/04/12632800.html
-Advertisement-
Play Games

前言 在上一篇中簡單介紹了Linq的入門級用法,這一篇嘗試講解一些更加深入的使用方法,與前一篇的結構不一樣的地方是,這一篇我會先介紹Linq里的支持方法,然後以實際需求為引導,分別以方法鏈的形式和類SQL的形式寫出來。 前置概念介紹 1. 謂詞、斷言,等價於 即返回bool的表達式 2. 表達式樹, ...


前言

在上一篇中簡單介紹了Linq的入門級用法,這一篇嘗試講解一些更加深入的使用方法,與前一篇的結構不一樣的地方是,這一篇我會先介紹Linq里的支持方法,然後以實際需求為引導,分別以方法鏈的形式和類SQL的形式寫出來。

前置概念介紹

  1. Predicate<T> 謂詞、斷言,等價於 Func<T,bool> 即返回bool的表達式
  2. Expression<TDelegate> 表達式樹,這個類很關鍵,但是在這裡會細說,我們會講它的一個特殊的泛型類型:Expression<Func<T,bool>> 這個在某些數據源的查詢中十分重要,它代表lambda表達式中一種特殊的表達式,即沒有大括弧和return關鍵字的那種。

我們先準備兩個類

  1. Student/學生類:
/// <summary>
/// 學生
/// </summary>
public class Student
{
    /// <summary>
    /// 學號
    /// </summary>
    public int StudentId { get; set; }
    /// <summary>
    /// 姓名
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 班級
    /// </summary>
    public string Class { get; set; }
    /// <summary>
    /// 年齡
    /// </summary>
    public int Age { get; set; }
}
  1. Subject/科目類:

    /// <summary>
    /// 科目
    /// </summary>
    public class Subject
    {
        /// <summary>
        /// 名稱
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 年級
        /// </summary>
        public string Grade { get; set; }
        /// <summary>
        /// 學號
        /// </summary>
        public int StudentId { get; set; }
        /// <summary>
        /// 成績
        /// </summary>
        public int Score { get; set; }
    }
    

Subject 和Student通過學號欄位一一關聯,實際工作中數據表有可能會設計成這。

那麼先虛擬兩個數據源:IEnumerable<Student> studentsIEnumerable<Subject> subjects。先忽略這兩個數據源的實際來源,因為在開發過程中數據來源有很多種情況,有資料庫查詢出來的結果、遠程介面返回的結果、文件讀取的結果等等。不過最後都會整理成IEnumerable<T>的子介面或實現類的對象。

常見方法介紹

Where 過濾數據,查詢出符合條件的結果

where的方法聲明:

public IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate)

可以看出不會轉換數據類型,通過給定的lambda表達式或者一個方法進行過濾,獲取返回true的元素。

示例:

// 獲取年紀大於10但不大於12的同學們
List<Student> results = students.Where(t=>t.Age >10 && t.Age<= 12).ToList();

註意在調用ToList之後數據才會實質上查詢出來。

Group 分組,依照指定內容進行分組

Group的方法聲明有很多種:

最常用的一種是:

public static IEnumerable<System.Linq.IGrouping<TKey,TSource>> GroupBy<TSource,TKey> (this IEnumerable<TSource> source, Func<TSource,TKey> keySelector);

示例:

//將學生按照班級進行分組
List<IGrouping<string,Student>> list = students.GroupBy(p => p.Class).ToList();

OrderBy/OrderByDescending 進行排序,按條件升序/降序

它們是一對方法,一個是升序一個降序,其聲明是一樣的:

常用的是:

public static System.Linq.IOrderedEnumerable<TSource> OrderBy<TSource,TKey> (this IEnumerable<TSource> source, Func<TSource,TKey> keySelector);

示例:

//按年齡的升序排列:
List<Student> results = students.OrderBy(p => p.Age).ToList();
//按年齡的降序排列:
List<Student> results = students.OrderByDescending(p => p.Age).ToList();

First/Last 獲取數據源的第一個/最後一個

這組方法有兩個常用的重載聲明:

First:

// 直接獲取第一個
public static TSource First<TSource> (this IEnumerable<TSource> source);
// 獲取滿足條件的第一個
public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);

Last:

// 直接獲取最後一個
public static TSource Last<TSource> (this IEnumerable<TSource> source);
// 獲取最後一個滿足條件的元素
public static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);

示例:

Student student = students.First();// 等價於 students[0];
Student student = students.First(p=>p.Class == "一班");//獲取數據源中第一個一班的同學

Student student = students.Last();//最後一個學生
Student student = students.Last(p=>p.Class == "三班");//獲取數據源中最後一個三班的同學

註意:

  • 在某些數據源中使用Last會報錯,因為對於一些管道類型的數據源或者說非同步數據源,程式無法確認最後一個元素的位置,所以會報錯。解決方案:先使用OrderBy對數據源進行一次排序,使結果與原有順序相反,然後使用First獲取
  • 當數據源為空,或者不存在滿足條件的元素時,調用這組方法會報錯。解決方案:調用FirstOrDefault/LastOrDefault,這兩組方法在無法查詢到結果時會返回一個預設值。

Any/All 是否存在/是否都滿足

Any:是否存在元素滿足條件

有兩個版本,不過意思可能不太一樣:

public static bool Any<TSource> (this IEnumerable<TSource> source);//數據源中是否有數據
//================
//是否存在滿足條件的數據
public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);

All :是否都滿足條件:

public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);

示例:

// 是否有學生
bool isAny =  students.Any();
// 是否有五班的同學
bool isFive = students.Any(p=>p.Class == "五班");
// 是否所有學生的年紀都不小於9歲
bool isAll = students.All(p=>p.Age >= 9);

Skip 略過幾個元素

Skip一共有三個衍生方法:

第一個:Skip 自己: 略過幾個元素,返回剩下的元素內容

public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count);

第二個:SkipLast,從尾巴開始略過幾個元素,返回剩下的元素內容

public static IEnumerable<TSource> SkipLast<TSource> (this IEnumerable<TSource> source, int count);

第三個:SkipWhile,跳過滿足條件的元素,返回剩下的元素

public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);

示例:

// 不保留前10個學生
List<Student> results = students.Skip(10).ToList();
// 不保留後10個學生
List<Student> results = students.SkipLast(10).ToList();
// 只要非一班的學生
List<Student> results = students.SkipWhere(p=>p.Class=="一班").ToList();
//上一行代碼 等價於 = students.Where(p=>p.Class != "一班").ToList();

Take 選取幾個元素

Take與Skip一樣也有三個衍生方法,聲明的參數類型也一樣,這裡就不對聲明做介紹了,直接上示例。

//選取前10名同學
List<Student> results = students.Take(10).ToList();
// 選取最後10名同學
List<Student> results = students.TakeLast(10).ToList();
//選取 一班的學生
List<Student> results = students.TakeWhile(p=>p.Class=="一班").ToList();
// 上一行 等價於 = students.Where(p=>p.Class=="一班").ToList();

在使用Linq寫分頁的時候,就是聯合使用Take和Skip這兩個方法:

int pageSize = 10;//每頁10條數據
int pageIndex = 1;//當前第一頁
List<Student> results = students.Skip((pageIndex-1)*pageSize).Take(pageSize).ToList();

其中 pageIndex可以是任意大於0 的數字。Take和Skip比較有意思的地方就是,如果傳入的數字比數據源的數據量大,根本不會爆粗,只會返回一個空數據源列表。

Select 選取

官方對於Select的解釋是,將序列中的每個元素投影到新的表單里。我的理解就是,自己 定義一個數據源單個對象的轉換器,然後按照自己的方式對數據進行處理,選擇出一部分欄位,轉換一部分欄位。

所以按我的理解,我沒找到java8的同效果方法。(實際上java用的是map,所以沒找到,

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #include<stdio.h> int main(void) { int a; scanf("%d",&a); switch(a) { case 1: printf("a"); case 2: printf("b"); case 3: printf("c\n"); } return 0; } d ...
  • #include<stdio.h> int main(void) { int a,b,c,d; printf("請輸入三個整數"); scanf("%d%d%d",&a,&b,&c); if (c>b) { d=b; b=c; c=d; } if (b>a) { d=a; a=b; b=d; } i ...
  • 1. 2.創建頭文件選擇C/C++ Header file 3.源程式文件與頭文件不在一個地址話,需要在導入的時候寫清楚頭文件所在地址 例如名為giligli.h的頭文件 #include”地址giligli.h” 4. 如圖D包含了兩個a 重覆定義會產生錯誤。利用條件編譯可以很好的避免重覆定義 # ...
  • 前言:在大一學習了C語言之後,基本掌握了一門面向過程的程式設計語言,本學期所學習的java是一門面向對象的語言,在問題的解決方面不像C一樣是以過程來思考問題,而是要以面向對象的思維來解決問題。此篇文章是對於本學期前三次Java作業的一個階段性總結,第一次作業花費了最多的時間,有一個測試點沒有過,第二 ...
  • 為表達全國各族人民對抗擊新冠肺炎疫情鬥爭犧牲烈士和逝世同胞的深切哀悼,國務院今天發佈公告,決定2020年4月4日舉行全國性哀悼活動。 當使用控制項模板時,需要決定如何更廣泛地共用模板,以及是否希望自動地或明確地位用模板。 第一個問題是關於希望在何處使用模板的問題。例如,是將它們限制在特定視窗中嗎?大多 ...
  • 2020年4月2日微軟.NET 團隊的項目經理 Richard 在博客上 發佈了.NET 5 Preview 2:https://devblogs.microsoft.com/dotnet/announcing-net-5-0-preview-2/ ,3月16號,Scott Hunter 在博客中發 ...
  • 前言 命名空間已經在 .NET 中使用了多年,一直追溯到 .NET Framework 1.1。它在 .NET 實施本身的數百個位置中使用,並且直接被成千上萬個應用程式使用。在所有這些方面,它也是 CPU 消耗的重要來源。 但是,從性能角度來看,正則表達式在這幾年間並沒有獲得太多關註。在 2006 ...
  • 在這篇文章中,我將詳細講解ASP.NET Core Project File.如果你還沒看我這個系列的前面幾篇文章,先去看看,打好基礎,再來看這篇吧。 如果你使用過之前版本的.NET Framework,你就會知道,當你使用C#創建應用程式的時候,.NET Framework框架將會創建尾碼名為”. ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...