介紹
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 時代 匿名方法
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反編譯一下
📷
匿名類 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 跌代器
- 基於委派封裝解構,去掉重複代碼
- 泛型,應對個總類型情況
- 加上跌代器,延遲獲取
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的語法
參考資料
我的鐵人賽文章
https://ithelp.ithome.com.tw/articles/10289873