一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

C# 基礎(chǔ)知識(shí)系列-7 Linq詳解

 頭號(hào)碼甲 2021-04-06

前言

在上一篇中簡(jiǎn)單介紹了Linq的入門級(jí)用法,這一篇嘗試講解一些更加深入的使用方法,與前一篇的結(jié)構(gòu)不一樣的地方是,這一篇我會(huì)先介紹Linq里的支持方法,然后以實(shí)際需求為引導(dǎo),分別以方法鏈的形式和類SQL的形式寫出來(lái)。

前置概念介紹

  1. Predicate<T> 謂詞、斷言,等價(jià)于 Func<T,bool> 即返回bool的表達(dá)式
  2. Expression<TDelegate> 表達(dá)式樹(shù),這個(gè)類很關(guān)鍵,但是在這里會(huì)細(xì)說(shuō),我們會(huì)講它的一個(gè)特殊的泛型類型:Expression<Func<T,bool>> 這個(gè)在某些數(shù)據(jù)源的查詢中十分重要,它代表lambda表達(dá)式中一種特殊的表達(dá)式,即沒(méi)有大括號(hào)和return關(guān)鍵字的那種。

我們先準(zhǔn)備兩個(gè)類

  1. Student/學(xué)生類:
/// <summary>
/// 學(xué)生
/// </summary>
public class Student
{
    /// <summary>
    /// 學(xué)號(hào)
    /// </summary>
    public int StudentId { get; set; }
    /// <summary>
    /// 姓名
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 班級(jí)
    /// </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>
        /// 年級(jí)
        /// </summary>
        public string Grade { get; set; }
        /// <summary>
        /// 學(xué)號(hào)
        /// </summary>
        public int StudentId { get; set; }
        /// <summary>
        /// 成績(jī)
        /// </summary>
        public int Score { get; set; }
    }
    

Subject 和Student通過(guò)學(xué)號(hào)字段一一關(guān)聯(lián),實(shí)際工作中數(shù)據(jù)表有可能會(huì)設(shè)計(jì)成這。

那么先虛擬兩個(gè)數(shù)據(jù)源:IEnumerable<Student> studentsIEnumerable<Subject> subjects。先忽略這兩個(gè)數(shù)據(jù)源的實(shí)際來(lái)源,因?yàn)樵陂_(kāi)發(fā)過(guò)程中數(shù)據(jù)來(lái)源有很多種情況,有數(shù)據(jù)庫(kù)查詢出來(lái)的結(jié)果、遠(yuǎn)程接口返回的結(jié)果、文件讀取的結(jié)果等等。不過(guò)最后都會(huì)整理成IEnumerable<T>的子接口或?qū)崿F(xiàn)類的對(duì)象。

常見(jiàn)方法介紹

Where 過(guò)濾數(shù)據(jù),查詢出符合條件的結(jié)果

where的方法聲明:

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

可以看出不會(huì)轉(zhuǎn)換數(shù)據(jù)類型,通過(guò)給定的lambda表達(dá)式或者一個(gè)方法進(jìn)行過(guò)濾,獲取返回true的元素。

示例:

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

注意在調(diào)用ToList之后數(shù)據(jù)才會(huì)實(shí)質(zhì)上查詢出來(lái)。

Group 分組,依照指定內(nèi)容進(jìn)行分組

Group的方法聲明有很多種:

最常用的一種是:

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

示例:

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

OrderBy/OrderByDescending 進(jìn)行排序,按條件升序/降序

它們是一對(duì)方法,一個(gè)是升序一個(gè)降序,其聲明是一樣的:

常用的是:

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 獲取數(shù)據(jù)源的第一個(gè)/最后一個(gè)

這組方法有兩個(gè)常用的重載聲明:

First:

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

Last:

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

示例:

Student student = students.First();// 等價(jià)于 students[0];
Student student = students.First(p=>p.Class == "一班");//獲取數(shù)據(jù)源中第一個(gè)一班的同學(xué)

Student student = students.Last();//最后一個(gè)學(xué)生
Student student = students.Last(p=>p.Class == "三班");//獲取數(shù)據(jù)源中最后一個(gè)三班的同學(xué)

注意:

  • 在某些數(shù)據(jù)源中使用Last會(huì)報(bào)錯(cuò),因?yàn)閷?duì)于一些管道類型的數(shù)據(jù)源或者說(shuō)異步數(shù)據(jù)源,程序無(wú)法確認(rèn)最后一個(gè)元素的位置,所以會(huì)報(bào)錯(cuò)。解決方案:先使用OrderBy對(duì)數(shù)據(jù)源進(jìn)行一次排序,使結(jié)果與原有順序相反,然后使用First獲取
  • 當(dāng)數(shù)據(jù)源為空,或者不存在滿足條件的元素時(shí),調(diào)用這組方法會(huì)報(bào)錯(cuò)。解決方案:調(diào)用FirstOrDefault/LastOrDefault,這兩組方法在無(wú)法查詢到結(jié)果時(shí)會(huì)返回一個(gè)默認(rèn)值。

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

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

有兩個(gè)版本,不過(guò)意思可能不太一樣:

public static bool Any<TSource> (this IEnumerable<TSource> source);//數(shù)據(jù)源中是否有數(shù)據(jù)
//================
//是否存在滿足條件的數(shù)據(jù)
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);

示例:

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

Skip 略過(guò)幾個(gè)元素

Skip一共有三個(gè)衍生方法:

第一個(gè):Skip 自己: 略過(guò)幾個(gè)元素,返回剩下的元素內(nèi)容

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

第二個(gè):SkipLast,從尾巴開(kāi)始略過(guò)幾個(gè)元素,返回剩下的元素內(nèi)容

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

第三個(gè):SkipWhile,跳過(guò)滿足條件的元素,返回剩下的元素

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

示例:

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

Take 選取幾個(gè)元素

Take與Skip一樣也有三個(gè)衍生方法,聲明的參數(shù)類型也一樣,這里就不對(duì)聲明做介紹了,直接上示例。

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

在使用Linq寫分頁(yè)的時(shí)候,就是聯(lián)合使用Take和Skip這兩個(gè)方法:

int pageSize = 10;//每頁(yè)10條數(shù)據(jù)
int pageIndex = 1;//當(dāng)前第一頁(yè)
List<Student> results = students.Skip((pageIndex-1)*pageSize).Take(pageSize).ToList();

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

Select 選取

官方對(duì)于Select的解釋是,將序列中的每個(gè)元素投影到新的表單里。我的理解就是,自己 定義一個(gè)數(shù)據(jù)源單個(gè)對(duì)象的轉(zhuǎn)換器,然后按照自己的方式對(duì)數(shù)據(jù)進(jìn)行處理,選擇出一部分字段,轉(zhuǎn)換一部分字段。

所以按我的理解,我沒(méi)找到j(luò)ava8的同效果方法。(實(shí)際上java用的是map,所以沒(méi)找到,

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    99国产高清不卡视频| 日本午夜免费啪视频在线| 国产一区二区三区丝袜不卡| 丁香七月啪啪激情综合| 尹人大香蕉中文在线播放| 黄色美女日本的美女日人| 久久精品国产亚洲av久按摩 | 日本加勒比在线播放一区| 九九热精品视频免费在线播放| 91天堂免费在线观看| 大胆裸体写真一区二区| 欧美韩日在线观看一区| 欧洲偷拍视频中文字幕| 99久久无色码中文字幕免费| 老富婆找帅哥按摩抠逼视频| 在线观看视频日韩精品| 久久香蕉综合网精品视频| 成人精品视频一区二区在线观看| 日本深夜福利在线播放| 夫妻性生活一级黄色录像| 欧美熟妇喷浆一区二区| 无套内射美女视频免费在线观看| 五月激情五月天综合网| 男人和女人干逼的视频| 91熟女大屁股偷偷对白| 欧美丰满大屁股一区二区三区| 久久99亚洲小姐精品综合| 国产又黄又猛又粗又爽的片 | 欧美一区二区不卡专区| 欧美成人国产精品高清| 久久精品久久久精品久久| 99一级特黄色性生活片| 亚洲成人免费天堂诱惑| 青青免费操手机在线视频| 蜜桃av人妻精品一区二区三区 | 99久久精品免费精品国产| 福利新区一区二区人口| 微拍一区二区三区福利| 久久国产精品热爱视频| 免费国产成人性生活生活片| 偷拍洗澡一区二区三区|