.NET基礎學習(LINQ)


什么是LINQ

  • LINQ(發音為link)代表語言集成查詢(Language Integrated Query)
  • 詳細見LINQ

匿名類型

第一個成員初始化器是賦值形式,第二個是成員訪問表達式,第三個是標示符形式,如下實例所示:

1 string Sex = "";
2 var person = new { Age = 24, SimpleClass.Name, Sex };
3 Console.WriteLine("{0},Sex{1},Age {2}",person.Name,person.Sex,person.Age);

運行結果:

注意標示符形式和訪問表達式必須定義在匿名類型申明之前,Sex是一個局部變量,Name是類SimpleClass的靜態字段。

盡管在代碼中看不到匿名類型,對象瀏覽器卻能看到。如果編譯器遇到了另一個具有相同參數名、相同引用類型名和相同順序的匿名類型,它會重用這個類型並直接創建新的實例,而不會創建新的匿名類型。

查詢語法和方法語法

  • 查詢語法(query syntax)是聲明形式的,看上去和SQL的語句很相似。查詢語法使用查詢表達式書寫。
  • 方法語法(method syntax)是命令形式,它的使用是標准的方法調用。方法是一組叫做標准查詢運算符的方法。
  • 在一個查詢中也可以組合以上兩種形式。

示例代碼如下所示:

 1 var query1 = from n in Enumerable.Range(1, 10)
 2 where n < 8
 3 select n;
 4 Console.Write("查詢語法得到結果:");
 5 foreach (var v in query1) Console.Write("{0}\t",v);
 6
 7 var query2 = Enumerable.Range(1, 8).Where(n => n < 8);
 8 Console.WriteLine("");
 9 Console.Write("方法語法得到結果:");
10 foreach (var v in query2) Console.Write("{0}\t", v);
11
12 int count = (from n in Enumerable.Range(1, 10)
13 where n < 8
14 select n).Count();
15 Console.WriteLine("");
16 Console.WriteLine("兩種方式的組合:{0}", count);

運行結果:

查詢表達式的結構

1、from子句

  • from子句指定了要作為數據源使用的數據集合。它也引入了迭代變量,迭代變量有序表示數據源的每一個元素。
1 int[] arr = { 1, 5, 9, 8, 45, 23, 26, 14, 7, 8, 9 };
2 var query = from n in arr //(n->迭代變量)
3 where n < 10 //使用迭代變量
4 select n; //使用迭代變量
5 foreach (var v in query) Console.Write("{0}\t",v);
6 Console.WriteLine("");

運行結果:

2、join子句

  • LINQ中的join子句和SQL中的join很相似,連接操作接受兩個集合然后創建一個臨時的對象集合,每個對象包含原始集合對象中的所有字段,使用連接來結合兩個或更多個集合中的數據。

示例代碼如下:

 1 public class Student
 2  {
 3 public int StID;
 4 public string LastName;
 5  }
 6 public class CourseStudent
 7  {
 8 public string CourseName;
 9 public int StID;
10  }
11
12 CourseStudent[] studentInCourses = new CourseStudent[]{
13 new CourseStudent{CourseName="Art",StID=1},
14 new CourseStudent{CourseName="Art",StID=3},
15 new CourseStudent{CourseName="History",StID=1},
16 new CourseStudent{CourseName="History",StID=2},
17 new CourseStudent{CourseName="Physics",StID=3}
18  };
19 Student[] students = new Student[] {
20 new Student{StID=1,LastName="張三"},
21 new Student{StID=2,LastName="李四"},
22 new Student{StID=3,LastName="王五"}
23  };
24
25 //獲取選修2門課以上同學的名字
26 var query = (from s in students
27 join c in studentInCourses on s.StID equals c.StID
28 where (from x in studentInCourses where x.StID==c.StID select x.StID).Count()>1
29 select s.LastName).Distinct();
30 foreach (var v in query) Console.Write("{0}\t",v);
31 Console.WriteLine("");
32 //獲取選修歷史同學的名字
33 var query1 = from s in students
34 join c in studentInCourses on s.StID equals c.StID
35 where c.CourseName == "History"
36 select s.LastName;
37 foreach (var v in query1) Console.Write("{0}\t", v);

運行結果:

查詢主體中的from...let...where片段

  • 可選的from...let...where部分是查詢主體的第一部分,可以由任意數量的3個子句來組合--from子句、let子句和where子句。

1、from子句

  • 查詢表達式必須從from子句開始,后面跟的是查詢主體。主體本身可以從任何數量的其他from子句開始,每一個from子句都指定了一個額外的數據源集合並引入了要在之后運算的迭代變量,所有from子句的語法和含義都是一樣的。

示例代碼如下:

1 var someInts = from a in Enumerable.Range(1, 5) //必須的第一個from子句
2 from b in Enumerable.Range(6, 5) //查詢主體的第一個子句
3 where a < 3 && b < 10
4 select new { a, b, sum = a + b }; //匿名類型對象
5 foreach (var v in someInts) Console.WriteLine(v);

 2、let子句

  • let子句接受一個表達式的運算並把它賦值給一個需要在其他運算中使用的標示符。

示例代碼如下:

1 var someInts = from a in Enumerable.Range(1, 5)
2 from b in Enumerable.Range(6, 5)
3 let sum = a + b //在新的變量中保存結果
4 where sum == 12
5 select new { a, b, sum };
6 foreach (var v in someInts) Console.WriteLine(v);

運行結果:

3、where子句

  • where子句根據之后的運算來去除不符合指定條件的項。

示例代碼如下:

1 var someInts = from a in Enumerable.Range(1, 5)
2 from b in Enumerable.Range(6, 5)
3 let sum = a + b
4 where sum > 12 //條件一
5 where a==4 //條件二
6 select new { a, b, sum };
7 foreach (var v in someInts) Console.WriteLine(v);

運行結果:

orderby子句

  • orderby子句接受一個表達式並根據表達式依次返回結果項,orderby子句的默認排序是升序,然而我們可以使用ascending和descending關鍵詞顯示第設置元素排序為升序或降序,ordery可以有任意多個子句,它們必須用逗號隔開。

示例代碼如下:

 1 var persons = new[] { //匿名類型的對象數組
 2 new {Name="張三",Sex="",Age=32,Address="廣東深圳"},
 3 new {Name="李四",Sex="",Age=26,Address="廣東廣州"},
 4 new {Name="王五",Sex="",Age=22,Address="廣東深圳"},
 5 new {Name="趙六",Sex="",Age=33,Address="廣東東莞"}
 6  };
 7 var query = from p in persons
 8 orderby p.Age
 9 select p;
10 foreach (var p in query) Console.WriteLine("Name:{0},Sex:{1},Age:{2},Address:{3}", p.Name, p.Sex, p.Age, p.Address);

運行結果:

group by子句

  • group子句把select的對象根據一些標准進行分組。例如,有了前面示例人的數組,程序可以根據它們的所在地進行分組。
  • group by如果項包含在查詢結果中,它們就可以根據某個字段的值進行分組。作為分組依據的項叫做鍵(key);和select子句不同,group子句不從原始的數據源中返回可枚舉的可枚舉類型,而是返回以枚舉已經形成的項的分組的可枚舉類型;分組本身是可枚舉類型,它們可枚舉實際的項。

示例代碼如下:

 1 var persons = new[] { //匿名類型的對象數組
 2 new {Name="張三",Sex="",Age=32,Address="廣東深圳"},
 3 new {Name="李四",Sex="",Age=26,Address="廣東廣州"},
 4 new {Name="王五",Sex="",Age=22,Address="廣東深圳"},
 5 new {Name="趙六",Sex="",Age=33,Address="廣東東莞"}
 6  };
 7 var query = from p in persons
 8  group p by p.Address;
 9 foreach (var v in query) //枚舉分組
10  {
11 Console.WriteLine("{0}",v.Key); //分組鍵
12 foreach (var t in v) //枚舉分組中的項
13  {
14 Console.WriteLine("Name:{0},Sex:{1},Age:{2},Address:{3}", t.Name, t.Sex, t.Age, t.Address);
15  }
16 }

運行結果:

查詢延續

  • 查詢延續子句可以接受查詢的一部分結果並賦予一個名字,從而可以查詢的另一部分中使用。

示例代碼如下:

1 var somInts = from a in Enumerable.Range(1, 10)
2 join b in Enumerable.Range(5, 10) on a equals b
3 into groupTemp //查詢延續
4 from c in groupTemp
5 select c;
6 foreach (var v in somInts) Console.WriteLine(v);

運行結果如下:

使用委托參數和Lambda的示例

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

示例代碼如下:

1 IList<int> list = Enumerable.Range(1, 100).ToList();
2 Func<int, bool> myDel = delegate(int x) { return x % 2 == 1; };//委托匿名方法
3 var countOdd1 = list.Count(myDel);//調用委托
4 var countOdd2 = list.Count(x => x % 2 == 1);//Lambda表達式
5 Console.WriteLine("委托參數得到奇數的個數:{0}",countOdd1);
6 Console.WriteLine("Lambda得到奇數的個數:{0}", countOdd2);

 

運行結果:

 版權所有,轉載請注明出處!

一切偉大的行動和思想,都有一個微不足道的開始。微不足道的我,正在吸取知識的土壤,希望能取得成功!不嫌棄我微不足道的,願交天下好友!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM