iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Software Development

玩轉C# 進階學習之旅系列 第 13

玩轉C#之【LINQ 基本介紹】

  • 分享至 

  • xImage
  •  

介紹

LINQ全名是(Language-Integrated Query),是一組以直接將查詢功能整合至C# 語言為基礎之技術的名稱。

大家可以想像SQL有SQL的查詢語法,MySql有MySql的查詢語法,但我們可以只透過LINQ語法,C#會自動幫我們轉換成對應的資料庫查詢語法,有點像是秦始皇統一文字的這種感覺。

歷史演進

C#1.0 1.1 時代 委派的做法

public class LambdaShow
{
    public delegate void NoReturnNoPara();//定義一個委派
    public delegate void NoReturnWthPara(int x,int y);//定義一個帶參數委派
    
    public voui Show()
    {
        NoReturnNoPara method = new NoReturnNoPara(this.Donothing);//實體化一個委派
    }

    private void DoNothing()
    {
        Console.WriteLine("Test");
    }
}

C# 2.0 時代 匿名方法

  • 除了可以少起方法名稱之外
  • 還可以讀取出K值
public voui Show()
{
    int k =1;
    NoReturnNoPara method = new NoReturnNoPara(delegate ()
    {
        Console.WriteLine(k);
        Console.WriteLine("Test");
    });
}

C# 3.0 時代 lambda

  • "=>" 稱之為goes to
  • 左邊是參數列表,右邊是方法體,本質是一個方法
public voui Show()
{
    NoReturnNoPara method = new NoReturnNoPara( () =>
    {
        Console.WriteLine("Test");
    });
}
//帶參數
public voui Show()
{
    NoReturnWthPara method = new NoReturnWthPara( (int x,int y) =>
    {
        Console.WriteLine("Test");
    });
}
//也可以省略參數型別
public voui Show()
{
    NoReturnWthPara method = new NoReturnWthPara( (x,y) =>
    {
        Console.WriteLine("Test");
    });
}
//如果方法體只有一行 可以去掉{} 跟;
public voui Show()
{
    NoReturnWthPara method = new NoReturnWthPara( (x,y) => Console.WriteLine("Test"));
}
//new NoReturnWthPara() 也可以省略掉
public voui Show()
{
    NoReturnWthPara method = (x,y) => Console.WriteLine("Test");
}

lambda表達式 是個什麼呢?

  • 首先不是委派,委派是類型
  • 也不是委派的實例 因為這裡是省略new 委派()
  • 只是一個方法(作用是一個方法) => 不完全正確
  • 編譯之後實際上是一個類中類,裡面的一個internal 方法,然後被綁定到靜態的委派類型

透過IL反編譯一下

IL

匿名類 var 擴展方法

普通的類別

    Student student = new Student()
    {
        Id =1,
        Name = "大禹治水",
        Age = 25,
        ClassId= 2
    };
    student.Study();

匿名類別 C#3.0

    object model = new
    {
        Id = 2,
        Name ="小帥哥",
        Age =25,
        ClassId= 2
    };
    Console.WriteLine(model.Id);//不能直接讀取Id 編譯器不允許通過

解決方式:

第一種

動態類型 C#4.0 =>可以避開編譯器檢查

    dynamic dModel =new
    {
        Id = 2,
        Name ="小帥哥",
        Age =25,
        ClassId= 2
    };
    Console.WriteLine(dModel.Id);
    dModel.Id =3;

第二種

用var C#3.0

實際上編譯後有一個真實的類別,從反編譯工具可以看出只有Get方法所以不能Set

 var dModel =new
    {
        Id = 2,
        Name ="小帥哥",
        Age =25,
        ClassId= 2
    };
    Console.WriteLine(dModel.Id);
    dModel.Id =3;//不能執行  因為只能Get 不能Set


IL反編譯一下

第三種

反射可以找到

var =>是一個語法糖,由編譯器自動推算類型
var =>宣告的時候就確定類型

    var i1 =1;
    var s="123";
    s=123;//宣告的時候就確定類型

擴充方法 C#3.0

    Student student = new Student()
    {
        Id =1,
        Name = "大禹治水",
        Age = 25,
        ClassId= 2
    };
    student.Study();

我們希望學生能有一個唱歌的功能,但不希望修改原本的類別,但是又要增加方法

首先要是一個靜態類別,裡面的一個靜態方法

public static class ExtenedMethod
{
    public static void Sing(Student student)
    {
        Console.WriteLine($"{student.Name} sing a Song");
    }
}

正常情況下使用方式

ExtendMethod.Sing(student);

如果我們在第一個參數前面加上一個this

public static class ExtenedMethod
{
    public static void Sing(this Student student)
    {
        Console.WriteLine($"{student.Name} sing a Song");
    }
}

可以變成這樣

student.Sing();

擴充方法就是在靜態類別,裡面的一個靜態方法,第一個參數前面加上一個this
用途:可以不修改類,增加方法也就是改變寫法方便了一點
缺點:優先調用類型的方法(有隱患),
擴充父類型,導致任何子類別都有這個方法,而且還有可能被覆蓋,最好指定類型擴充

Linq to object

一般情況過濾數據

    
    var list = new List<Student>();
    foreach(var item in studentList)
    {
        if(item.Age < 30)
        {
            list.Add(item);
        }
    }

等價的做法

public static class ExtendMethod
{
    public static List<Student>EleventWhere(this Kust<Student> source,Func<Student,bool> func)
    {
         var list = new List<Student>();
        foreach(var item in source)
        {
            if(func.Invoke(item))
            {
                list.Add(item);
            }
        }
        
    }
}
    var result = list.EleventWhere(x=>x.Age < 30);//陳述式語法

yield 跌代器

  1. 基於委派封裝解構,去掉重複代碼
  2. 泛型,應對個總類型情況
  3. 加上跌代器,延遲獲取
public static IEnumberable<T> ElevenWhere<T>(this IEnumberable<T> source,Func<T,bool> func)
{
    foreach(var item in source)
    {
        if(func.Invoke(item))
        {
            yield return item;
        }
    }
}

linq常用方法介紹

Where =>篩選
Select=>轉換
Min/Max/OrderBy/

Linq To Object(Enumerable)
Linq To Sql(Queryable) =>SQL+ADO.NET 表達式目錄樹解析SQL

下一章節會正式介紹LINQ的語法

參考資料

語言整合式查詢 (LINQ) (C#)

本篇已同步發表至個人部落格
https://moushih.com/2022ithome13/


上一篇
玩轉C#之【序列化、反序列化】
下一篇
玩轉C#之【LINQ 語法介紹】
系列文
玩轉C# 進階學習之旅31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言