Linq lambda 匿名方法

課程6  委託、匿名方法、Lambda表達式、Linq查詢表達式
上課日誌1
1、委託的基本認識
提問:能不能把方法做爲參數傳遞???
也便是能不能聲明一個能存放方法的變量呢——委託。
委託是一種數據類型,像類同樣(能夠聲明委託類型變量),委託是用來接受方法的,經過委託能夠把方法做爲參數進行傳遞。
namespace _01委託的基本認識
{
    //1.定義委託類型。定義一個委託類型(委託是一種數據類型,能接受方法的數據類型),用來保存無參數,無返回值的方法
    //委託最好要定義在命名空間中,和類是同一個級別
    public delegate void MyDelegate();//也像定義抽象方法同樣,沒有實現(方法體)
    // public class MyClass { } //這是定義一個類

    class Program
    {
        //void Run();//定義抽象方法
        //string Test();//定義抽象方法
        static void Main(string[] args)
        {
            //2.使用委託第二步:聲明委託變量,並賦值
            //聲明瞭一個委託變量md,而且new了一個委託對象,而且把方法M1傳遞了進去
            //即md委託保存了M1方法

            //MyClass mc=new MyClass();
            //MyDelegate md = new MyDelegate(M1);//第1種寫法
            MyDelegate md = M1;////第2種寫法
           
            //3.調用md委託的時候就至關於調用M1方法
            md();//與下面那就等同
            //md.Invoke();//Invoke()的做用是執行指定的委託
            Console.WriteLine("ok");
            Console.ReadKey();
        }
        static void M1()
        {
            Console.WriteLine("我是一個沒有參數沒有返回值的方法");
        }
}
}
2、委託的基本應用舉例1
需求:假設一件事情在前面和後面要作的事情比較固定(這裏假設輸出「========」),可是中間要作的事情常常發生變化(好比1.要輸出系統當前時間到控制檯,2.要輸出系統當前是星期幾,3.要把系統時間寫入到文本文件等)
namespace _02委託的基本應用
{
    //定義一個委託
    public delegate void middleDelegate();

    public class TestClass
    {
        public void DoSomething(middleDelegate middleThing)//委託類型做爲參數,也便是調用此方法要傳遞一個方法進來
        {
           Console.WriteLine("==========================");
           Console.WriteLine("==========================");
            //執行完第二句代碼,輸出下系統時間 
//Console.WriteLine(System.DateTime.Now.ToString());
            if (middleThing != null)//委託是一個對象,就有可能爲null,因此先判斷下是否爲null
            {
                middleThing ();
            }
           Console.WriteLine("==========================");
           Console.WriteLine("==========================");
        }
    }
}
namespace DelegateApp1
{
    class Program
    {
        static void Main(string[] args)
        {       
            TestClass tc = new TestClass();
            tc.DoSomething(PrintTimeToConsole);
            Console.ReadKey();
        }
        public static void PrintTimeToConsole()
        {
Console.WriteLine(System.DateTime.Now.ToString());
        }
        static void writeTimeToFile()
        {
            File.WriteAllText("time.txt", System.DateTime.Now.ToString());
        }
        public static void PrintWeekToConsole()
        {
Console.WriteLine(System.DateTime.Now.DayOfWeek.ToString());
        }    
}
}
3、委託的基本應用舉例2與總結
從上例能夠看出委託通常是在一個方法(1)的一大段程序中間「挖個坑」,這個坑用來執行另外一個方法(2),而這個方法(2)是動態的,能夠根據須要調用不一樣的方法到方法(1)中。
需求:對字符串的處理常常要發生變化,好比在字符串兩端加「=」、加「★」,把字符串字母所有轉換爲大寫。
namespace _03委託的基本應用練習與總結
{
    //定義一個委託(委託是一種數據類型,接受方法的數據類型)
    public delegate string GetStringDelegate(string str);

    public class TestClass
    {
        public void ChangeStrings(string[] strs, GetStringDelegate GetString)
        {
            for (int i = 0; i < strs.Length; i++)
            {
                strs[i] = GetString(strs[i]);//因爲對字符串的需求有不少種,因此把對字符串變化部分用委託封裝成一個方法
            }
        }
    }
}

static void Main(string[] args)
        {
            TestClass tc = new TestClass();
            string[] names = new string[] { "ZhangSan", "LiSi", "WangWu", "LaoLiu" };
            /*下面就能夠調用含有委託的方法,若是須要在字符串兩端加★,就調用ChangesStrings2方法
            /若是須要把字符串的字母轉換爲大寫,就調用ChangesStrings3方法,這樣就靈活了*/
            //tc.ChangeStrings(names, ChangesStrings1);//應用需求1
            //tc.ChangeStrings(names, ChangesStrings2);//應用需求2
            tc.ChangeStrings(names, ChangesStrings3);//應用需求3
            //把變化後的字符串數組中的字符串輸出
            for (int i = 0; i < names.Length; i++)
            {
                Console.WriteLine(names[i]);
            }
            Console.ReadKey();
        }
        static string ChangesStrings3(string str)//需求3:把字符串中字母轉換爲大寫
        {
            return str.ToUpper();
        }
        static string ChangesStrings2(string strs)//需求2:在字符串兩端加★
        {
            return "" + strs + "";
        }
        static string ChangesStrings1(string strs)//需求1:在字符串兩端加★
        {
            return "=" + strs + "=";
        }
委託認識的總結:
委託是一種數據類型,像類同樣的一種數據類型。通常都是直接在命名空間中定義。
定義委託時,須要指明返回值類型、委託名與參數列表,這樣就能肯定該類型的委託能存儲(接受)什麼樣的方法。
使用委託
(1)聲明委託變量
(2)委託是一個引用類型,就像類同樣,因此當聲明委託變量後,若是不賦值則該委託變量爲null。因此在使用委託變量前最好作非空校驗if(weituo!=null)

4、泛型委託Action與Action<T>
1、Action委託(非泛型版本)
例1 :
public delegate void Mydelegate();
    class Program
    {
        static void Main(string[] args)
        {
            Mydelegate md = new Mydelegate(M1);
            md();
            //系統內置了三種委託,像這種委託就能夠用系統內置委託Action,徹底不用自已寫。Action委託就是一個無參數無返回值的委託(非泛型版本)
            Action action = M1;
            action();
            Console.ReadKey();
        }
        static void M1()
        {
            Console.WriteLine("ok");
        }
} 
2、本身寫泛型委託
例2:若是本身寫非泛型委託:須要保存一個string類型參數,但無返回值的方法,就須要寫一個委託
須要保存一個int類型參數,但無返回值的方法,就須要再寫一個委託
須要保存一個bool類型參數,但無返回值的方法,就須要再另外寫一個委託等等,這樣的話就得寫不少委託,
因而咱們就能夠寫泛型委託,一次性搞定。
public delegate void Mydelegate1(string msg);
    public delegate void Mydelegate2(int msg);
    public delegate void Mydelegate3(bool msg);
    
    public delegate void MyGenericdelegate<T>(T args);//這個委託就能夠接受1個參數,無返回值的方法,可是這個參數數據類型能夠任意
    class Program
    {
        static void Main(string[] args)
        {
            MyGenericdelegate<string> md1 = M1;
            md1("一個參數");
            MyGenericdelegate<int> md2 = M1;
            md2(1);
            MyGenericdelegate<bool> md3 = M1;
            md3(true);
            Console.ReadKey();
        }
        static void M1(string msg)
        {
            Console.WriteLine(msg);
        }
        static void M1(int msg)
        {
            Console.WriteLine(msg);
        }
        static void M1(bool b)
        {
            Console.WriteLine(b);
        }
}

這種狀況就能夠直接使用系統提供的泛型委託Action<T>3、Action<T>委託(泛型版本)
Action<T>委託的泛型版本是一個無返回值,可是參數個數及類型能夠改變的委託。
例子3:
class Program
    {
        static void Main(string[] args)
        {
            Action<string> action1 = M1;
            action1("內置無返回值的泛型委託");
            Action<int> action2 = M1;
            action2(12);
            Action<bool> action3=M1;
            action3(true);
            Console.ReadKey();
        }
        static void M1(string msg)
        {
            Console.WriteLine(msg);
        }
        static void M1(int msg)
        {
            Console.WriteLine(msg);
        }
        static void M1(bool b)
        {
            Console.WriteLine(b);
        }
}

系統提供了三種委託,因此之後通常不須要本身去定義委託,直接用系統內部提供的就能夠
Action——Action委託的非泛型版本就是一個無參數無返回值的委託
Action<T>——Action<T>委託的泛型版本是一個無返回值,可是參數個數及類型能夠改變的委託
Func<T>——Func委託只有泛型版本的,接受參數個數能夠是若干個,也能夠是沒有參數,可是必定有返回值的方法(下節講)


課程6  委託、匿名方法、Lambda表達式、LINQ查詢表達式

上課日誌2數據庫

補充—VS中自定義C#快速簡寫代碼(輸入簡寫字母后按兩次Tab鍵自動輸入 express

VS中選擇工具——>代碼段管理器(語言下拉框選擇Visual C#以下圖1所示),位置下面的下拉列表框再選擇Visual C#而後複製位置文本框裏的路徑即找到代碼段簡寫文件(*.snippet)。數組

而後隨便複製一個(好比cw.snippet)複製的位置能夠任意(注意兩點第1、不要在原來的cw.snippet位置,第2、須要新建一個文件夾zdy)來存儲複製過來cw.snippet文件架構

而後再對複製過來的文件修改(好比須要建立快速輸入Console.ReadKey(),能夠把文件名改成crk.snippet),接着打開重命名後的文件crk.snippet)修改裏面的內容(如2所示),參照3進行修改修改綠色框住的4個地方便可函數

最後單擊1下面的添加按鈕,選擇到自定義的文件夾zdy)。工具

 

1性能

 

2學習

 

3spa

2、泛型委託Func<T>

Fun<T>——Func委託只有泛型版本的,接受參數個數能夠是若干個,也能夠是沒有參數,可是必定有返回值的方法日誌

Func<TResult>這個表示沒有參數,只有返回值的

Func<T,TResult>這個表示有1個參數,有返回值的

Func<T1,T2,TResult>這個表示有2個參數(前兩個參數T1,T2表示參數,最後TResult返回值),有返回值的

Func<T1,T2,T3,TResult>這個表示有3個參數(前三個參數T1,T2,T3,表示參數,最後TResult返回值),有返回值的.

總之Func委託最後一個TResult表示返回值,前面的無論多少個T都是表示參數

例:

class Program

    {

        static void Main(string[] args)

        {

            #region 無參數有返回值的Fun委託

            Func<int> fun1 = M1;

            int n1 = fun1();

            Console.WriteLine(n1);

            #endregion

 

            #region 有參數有返回值的Fun委託

            Func<int, int, int, int> fun2 = M2;

            int n2 = fun2(1, 2, 3);

            Console.WriteLine(n2);

            #endregion           

            Console.ReadKey();

        }

        static int M1()

        {

            return 1;

        }

        static int M2(int n1, int n2, int n3)

        {

            return n1 + n2 + n3;

        }

}

3、多播委託

多播委託就是一個委託同時綁定多個方法多播委託也叫委託鏈、委託組合

一、綁定無返回值的多個委託

class Program

    {

        static void Main(string[] args)

        {

            #region 綁定無返回值的多個委託

            Action<string> action = M1;//這句話只綁定一個M1方法(綁定第一個方法不能用+=複製,由於開始actionnull,因此只能用=賦值),下面再給acion綁定方法

            action += M2;

            action += M3;

            action += M4;

            action += M5;

            action -= M3;//解除綁定M3方法(便是用-=賦值爲解除綁定方法)

            action("多播委託");

            #endregion           

            Console.ReadKey();

        }

        static void M1(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M2(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M3(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M4(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M5(string msg)

        {

            Console.WriteLine(msg);

        }

}

二、綁定返回值的多個委託如何獲取到每一個方法的返回值

class Program

    {

        static void Main(string[] args)

        {

            #region 綁定有返回值的多個委託

            Func<string, string> fc = T1;

            fc += T2;

            fc += T3;

           string result= fc("有參數有返回值的多播委託");

           Delegate[] delegates = fc.GetInvocationList();//按照調用順序返回此多播委託的調列表。便是有幾個方法就有個幾個委託,返回值爲Delegate數組

           for (int i = 0; i < delegates.Length; i++)//循環遍歷Delegate數組便可獲得每一個委託對象.這樣就能夠逐個委託調用,若是有返回值,能夠逐個拿到

           {

               //delegates[i](「……」);這句不行,由於Delegate是抽象類,因此不能直接調用,須要強轉爲子類                //(delegates[i] as Func<string,string>)();//沒有返回值就這樣就能夠,若是有返回值相似下一行代碼就能夠

               string s = (delegates[i] as Func<string, string>)("獲取多播委託每一個方法的返回值");

               Console.WriteLine(s);

           }

            #endregion

            Console.ReadKey();

        }

        static string T1(string msg)

        {

            return msg+"1";

        }

        static string T2(string msg)

        {

            return msg + "2";

        }

        static string T3(string msg)

        {

            return msg + "3";

        }

}

4、匿名方法

一、匿名類

static void Main(string[] args)

        {

            #region 匿名類

            var Anon = new { Name = "小明", Age = 3, Sex = '' };

            Console.WriteLine("個人名字是:{0},性別爲{1},年齡是{2}", Anon.Name, Anon.Sex, Anon.Age);

            Console.ReadKey();

            #endregion

        }

二、匿名方法

 匿名方法,便是沒有名字的方法,不能直接在類中定義,而是在給委託變量賦值的時候,須要賦值一個方法,此時能夠「現作現賣」,定義一個匿名方法傳遞給該委託。

匿名方法關鍵字delegate,delegate後的括號寫方法參數,{ }裏面寫方法體,這是一個賦值語句因此最後須要分號

1:

  #region 匿名方法無參數無返回值

            //若是存在一個已定義好的M1方法,則直接能夠把該方法賦給委託變量md 

           // Action md = M1; 

            //若是不存在已定義好的方法,則可使用匿名方法賦給委託變量,即現定義一個方法給委託變量

            Action  md = delegate()

            {

                Console.WriteLine("ok");

            };

            md();//調用匿名方法

            Console.ReadKey();

            #endregion

  static void M1()

        {

            Console.WriteLine("ok");

        }

2:

#region 有參數無返回值的匿名方法

            Action<string> md2 = delegate(string msg)

            {

                Console.WriteLine("Hello" + msg);

            };

            md2("你們好!");

            Console.ReadKey();

            #endregion

3:

#region 有參數有返回值的匿名方法

            Func<int,int,int,int> ad = delegate(int n1, int n2, int n3)//提問:這裏若是不採用匿名方法怎麼寫

            {

                return n1 + n2 + n3;

            };

            int result = ad(12, 10, 8);

            Console.WriteLine(result);

            Console.ReadKey();

            #endregion

5、Lambda表達式

一、Lambda介紹

「Lambda 表達式」(lambda expression)就是一個匿名函數(匿名方法),Lambda表達式基於數學中的λ演算得名。

  Lambda運算符:全部的lambda表達式都是用新的lambda運算符 " => ",能夠叫他:「轉到」或者 「成爲」,讀做 「goes to」。運算符將表達式分爲兩部分,左邊指定輸入參數右邊是lambda的主體(方法體)

        lambda表達式:

             一個參數:param=>expr

            多個參數:(param-list)=>expr

二、輸入參數與表達式或語句塊

輸入參數:在Lambda表達式中,輸入參數是Lambda運算符的左邊部分。它包含參數的數量能夠爲0、1或者多個。只有當輸入參數爲1時Lambda表達式左邊的一對小括弧才能夠省略。輸入參數的數量大於或者等於2時,Lambda表達式左邊的一對小括弧中的多個參數之間使用逗號(,)分割

表達式或語句塊:多個Lambda表達式能夠構成Lambda語句塊。語句塊是放到運算符的右邊,做爲Lambda的主體。語句塊中能夠包含多條語句,而且能夠包含循環、方法調用和if語句等。語句塊必須被"{"和"}"包圍。

 

1:無參數、表達式

#region 參數

//Action a = () => { Console.WriteLine("This is a Lambda expression."); };

Action a= ()=>Console.WriteLine("This is a Lambda expression.");

          a();

Console.ReadKey();

  #endregion

因爲上述Lambda表達式的輸入參數的數量爲0,所以,該Lambda表達式的左邊部分的一對小括弧不能被省略。右邊是一個表達式

 

2:1個參數狀況、語句塊

  #region 1個參數

            Action<int> b = m => { int n = m * 2; Console.WriteLine(n); };//此處參數m的括號能夠省略

            b(2);

#endregion

上述Lambda表達式的輸入參數省略了一對小括弧,它與「(m)=> { int n = m * 2; Console.WriteLine(n); };是等效的。右邊是語句塊,那麼該語句塊必須被"{"和"}"包圍,還有return語句不能省略花括號

 

3:多個參數、語句塊

  #region 多個參數

  Action<int,int> c = (m,n) => { int s = m * n; Console.WriteLine(s); };//此處參數的括號不能省略

            c(2,3);

#endregion

6、匿名方法、Lambda表達式應用鞏固舉例

1、匿名方法與Lambda的替

static void Main(string[] args)

        {

            //Func<int, int, int, int> ad = M2;

            #region 有參數有返回值的匿名方法

            Func<int, int, int, int> ad = delegate(int n1, int n2, int n3)//該匿名方法實際上與下面的有名方法M2同樣

            {

                return n1 + n2 + n3;

            };

            int result = ad(12, 10, 8);

            Console.WriteLine(result);

            #endregion

 

            #region 有參數有返回值的lambda表達式

            Func<int, int, int, int> ad2 = (x, y, z) => { return x + y + z; };

            int r = ad2(10, 20, 30);

            Console.WriteLine(r);

            #endregion

            Console.ReadKey();

        }

        static int M2(int n1, int n2, int n3)

        {

            return n1 + n2 + n3;

        }

說明:匿名方法、lambda表達式運行時最終都會編譯成方法

2定義一個能接收參數個數可變有返回值的委託

public delegate int Adddelegate(params int[] arr);//定義一個能接收參數個數可變且有返回值的委託

static void Main(string[] args)

        {

            #region 接收參數個數可變的lambda表達式

            Adddelegate ad = (arr) =>

            {

                for (int i = 0; i < arr.Length; i++)

                {

                    Console.WriteLine(arr[i]);

                }

                return arr.Sum();

            };

            int x = ad(1, 2, 3, 4, 5);

            Console.WriteLine(x);

            Console.ReadKey();

            #endregion

        }

3lambda表達式在泛型集合中的應用

示例:打印出泛型集合中大於6的元素。

static void Main(string[] args)

        {

List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 89, 10, 11, 12, 13, 14, 15 };

           //第一種寫法本身定義方法

            IEnumerable<int> ie = list.Where(cs); //var

            //第二種寫法用匿名方法

            //IEnumerable<int> ie = list.Where(delegate(int n)

            //{

            //    return n > 6;

            //}

            //    );//where裏面須要一個方法做爲參數(有1int類型參數,返回值爲bool類型)           

            //第三種寫法使用lambda表達式

            //IEnumerable<int> ie = list.Where(n => { return n > 6; });

            foreach (var item in ie)

            {

                Console.WriteLine(item);

            }

            Console.ReadKey();

           #endregion

        }

        static bool cs(int n)

        {

            return n > 6;

        }

7、Linq簡介

LINQ的全稱是Language Integrated Query,中文譯成「語言集成查詢」。LINQ一種查詢技術,LINQ to SQL、LINQ to Object、LINQ to ADO.NET、LINQ to XMLLINQ to EF等

LINQ與直接SQL語句比較:

1)SQL數據庫技術是一門相對比較複雜深奧的技術,不是人人都懂,而LINQ To SQL比較簡單(實際上底層都對數據庫操做進行了封裝,架構了數據訪問層)

2)直接寫SQL語句,若是有問題,只有到運行時才知道

3)LINQ To SQL能夠很好的防止注入式攻擊

4)Linq是面向對象的查詢,主要在程序內部使用(好比查找所需的數據),比使用DataReader讀取數據等方便多了;直接SQL是面向關係型數據庫的查詢

5)從運行效率上來講性能不如直接SQL語句,可是開發效率提升了。

要學習LINQ首先就要學習LINQ查詢表達式。

LINQ的查詢由3基本部分組成:獲取數據源,建立查詢,執行查詢。

// 1.獲取數據源

            List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            // 2.建立查詢

            var numQuery = from num in numbers

                           where num % 2 == 0

                           select num*10;

//SQL語句比較下

//string ql=」select StuName from Student where ID>1」

            // 3.執行查詢

            foreach (var num in numQuery)

            {

                Console.WriteLine(num);

           }

LINQ 中,查詢的執行與查詢自己大相徑庭;換句話說,若是隻是建立查詢變量,則不會檢索任何數據。

Linq的數據源要求必須實現IEnumerable或IEnumerable<T>接口,數組隱式支持這個接口numQuery叫作查詢變量,它存儲了一個查詢表達式。注意,聲明查詢變量並不會執行查詢,真正的執行查詢延遲到了foreach語句中

查詢表達式必須以from子句開頭,以select或group子句結束。第一個from子句和最後一個select子句或group子句之間,能夠包含一個或多個where子句、let子句、join子   句、orderby子句和group子句,甚至還能夠是from子句。它包括8個基本子句,具體說明以下所示。

●from子句:指定查詢操做的數據源和範圍變量。

●select子句:指定查詢結果的類型和表現形式。

●where子句:指定篩選元素的邏輯條件。

●let子句:引入用來臨時保存查詢表達式中的子表達式結果的範圍變量。

●orderby子句:對查詢結果進行排序操做,包括升序和降序。

●group子句:對查詢結果進行分組。

●into子句:提供一個臨時標識符。join子句、group子句或select子句能夠經過該標識符引用查詢操做中的結果。

●join子句:鏈接多個用於查詢操做的數據源。

8、Form子句

建立一個LINQ表達式必需要以from子句開頭。

1:單個Form子句

string[] values = { "中國", "日本", "美國", "菲律賓", "越南" };

            //查詢包含「國」的字符串

// IndexOf查詢參數字符串在父串中首次出現的位置,沒有返回-1

            var valueQuery = from v in values

                             where v.IndexOf("") > 0

                             select v;

            foreach (var v in valueQuery)

            {

                Console.WriteLine(v);

            }

            Console.ReadKey();

在這個LINQ表達式的from子句中,v叫作範圍變量,values是數據源。v的做用域存在於當前的LINQ表達式,表達式之外不能訪問這個變量。where用來篩選元素,select用於輸出元素。這裏的範圍變量v和foreach語句中隱式變量v均可以由編譯器推斷出其類型

2:複合Form子句

在查詢數據源中,元素的屬性是一個集合時,可使用複合from子句對這個屬性集合查詢。好比,一個客戶,可能有多個電話。

class CustomerInfo

    {

        public string Name { get; set; }

        public int Age { get; set; }

        public List<string> TelTable { get; set; }

    }

static void Main(string[] args)

        {

            formExpDemo();

            Console.ReadKey();

        }

        static void formExpDemo()

        {

            List<CustomerInfo> customers = new List<CustomerInfo> {

                                           new CustomerInfo{ Name="歐陽曉曉", Age=35, TelTable=new List<string>{"1330708****","1330709****"}},

                                           new CustomerInfo{ Name="上官飄飄", Age=17, TelTable=new List<string>{"1592842****","1592843****"}},

                                           new CustomerInfo{ Name="諸葛菲菲", Age=23, TelTable=new List<string>{"1380524****","1380525****"}}

                                           };

            //查詢包含電話號碼1592842****的客戶

            var query = from CustomerInfo ci in customers//ci

                        from tel in ci.TelTable

                        where tel.IndexOf("1592842****") > -1

                        select ci;

 

            foreach (var ci in query)

            {

                Console.WriteLine("姓名:{0} 年齡:{1}", ci.Name, ci.Age);

                foreach (var tel in ci.TelTable)

                {

                    Console.WriteLine("          電話:{0}", tel);

                }

            }

}

9、where子句select子句

1where子句

where子句的做用就是篩選元素,除了開始和結束位置,where子句幾乎能夠出如今LINQ表達式的任意位置。一個LINQ表達式中能夠有where子句,也能夠沒有;能夠有一個,能夠有多個;多個where子句之間的關係至關於邏輯「與」,每一個where子句能夠包含1個或多個邏輯表達式,這些條件成爲「謂詞」,多個謂詞之間用布爾運算符隔開,好比邏輯「與」用&&,邏輯「或」用||,而不是用SQL中的AND或OR。

class CustomerInfo

    {

        public string Name { get; set; }

        public int Age { get; set; }

        public string Tel { get; set; }

    }

List<CustomerInfo> clist = new List<CustomerInfo> {

new CustomerInfo{ Name="歐陽曉曉", Age=35, Tel ="1330708****"},

new CustomerInfo{ Name="上官飄飄", Age=17, Tel ="1592842****"},

new CustomerInfo{ Name="令狐沖", Age=23, Tel ="1380524****"}

                                                   };

            //查詢名字是3個字或者姓「令」的,但年齡大於20的客戶

            var query = from customer in clist

                        where (customer.Name.Length == 3 || customer.Name.Substring(0, 1) == "") && customer.Age > 20

                        select customer;

            foreach (var ci in query)

            {

                Console.WriteLine("姓名:{0} 年齡:{1} 電話:{2}", ci.Name, ci.Age, ci.Tel);

            }

2select子句

1:最簡單的select就是直接輸出from子句創建的那個範圍變量:

#region 簡單的select示例

            int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        select n;  //select n*10;對象.屬性

     #endregion

2:對查詢結果進行投影(轉換)。下面查詢表達式查詢arr數組中的每個元素,查詢結果轉換爲一個集合對象兩個屬性ID和Name,它在select子句中由匿名對象初始化器建立。每個對象的ID屬性的值是當前元素的值、Name屬性的值爲元素的值的字符串的表現形式。

#region 對查詢結果進行投影(轉換)

            int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        select new

                        {

                            ID = n,

                            Name = n.ToString()

                        };

            foreach (var item in query)

            {

                Console.WriteLine(item.ID+"  "+item.Name);

            }

            Console.ReadKey();

 #endregion

 

10、Group子句into子句orderby子句

1Group子句

LINQ表達式必須以from子句開頭,以select或group子句結束,因此除了使用select子句外,也可使用guoup子句來返回元素分組後的結果。group子句用來將查詢結果分組,並返回一對象序列。這些對象包含零個或更多個與該組的key值匹配的項。

注意:每個分組都不是單個元素,而是一個序列(也屬於集合)。序列的元素類型爲IGrouping<TKey,TElement>(必須Group子句結束的LINQ表達式,分組結果類型才爲序列序列的元素類型爲IGrouping<TKey,TElement>)

List<CustomerInfo> clist = new List<CustomerInfo> {

  new CustomerInfo{ Name="歐陽曉曉", Age=35, Tel ="1330708****"},

  new CustomerInfo{ Name="上官飄飄", Age=17, Tel ="1592842****"},

  new CustomerInfo{ Name="歐陽錦鵬", Age=35, Tel ="1330708****"},

  new CustomerInfo{ Name="上官無忌", Age=23, Tel ="1380524****"}

                                                   };

 

            //按照名字的前2個字進行分組

    var query = from customer in clist

                group customer by customer.Name.Substring(0, 2);

 

    //foreach (IGrouping<string, CustomerInfo> group in query)

    foreach (var group in query)

    {

        Console.WriteLine("分組鍵:{0}", group.Key);

        foreach (var ci in group)

        {

             Console.WriteLine("姓名:{0} 電話:{1}", ci.Name, ci.Tel);

       }

                Console.WriteLine("***************************************");

}

2into子句

into子句能夠用來建立一個臨時標識符,將group、join或select子句的結果存儲到這個標識符中。

int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        where n > 1 && n < 6

                        group n by n % 2 into g

                        from sn in g

                        select sn;

            

                foreach (var item in query)

                {

                    Console.WriteLine(item);

                }

3orderby子句(中間無空格

orderby子句可以使返回的查詢結果按升序或者降序排序。升序由關鍵字ascending指定,而降序由關鍵字descending指定。

注意:orderby子句默認排序方式爲升序。

示例1:

int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        where n > 1 && n < 6

                        orderby n descending

                        select n;

示例2:

int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        where n > 1 && n < 6

                        orderby n % 2 ascending, n descending

                        select n;

n%2:按照升序排序;n:按照降序排序。

注意:n%2排序關鍵字優先級大於n排序關鍵字。所以,該查詢表達式的結果首先按照n%2排序關鍵字升序排序,而後再按照n排序關鍵字降序排序。第一個排序關鍵字後的"ascending"能夠省略。由於默認排序方式爲升序。

11、let子句join子句

1let子句

let子句用於在LINQ表達式中存儲子表達式的計算結果。let子句建立一個範圍變量來存儲結果,變量被建立後,不能修改或把其餘表達式的結果從新賦值給它。此範圍變量能夠後續的LINQ子句中使用。 

List<CustomerInfo> clist = new List<CustomerInfo> {

              new CustomerInfo{ Name="歐陽曉曉", Age=35, Tel ="1330708****"},

              new CustomerInfo{ Name="上官飄飄", Age=17, Tel ="1592842****"},

              new CustomerInfo{ Name="郭靖", Age=17, Tel ="1330708****"},

              new CustomerInfo{ Name="黃蓉", Age=17, Tel ="1300524****"}

                                                   };

 

            //「郭」或「黃」的客戶

            var query = from customer in clist

                        let g = customer.Name.Substring(0, 1)

                        where g == "" || g == ""

                        select customer;

            foreach (var ci in query)

            {

                Console.WriteLine("姓名:{0} 年齡:{1} 電話:{2}", ci.Name, ci.Age, ci.Tel);

            }

 

//where customer.Name.Substring(0, 1) == "郭" || customer.Name.Substring(0, 1) == "黃"

2join子句

join子句用來鏈接兩個數據源,即設置兩個數據源之間的關係。join子句支持如下3種常見聯接方式。

內部聯接:要求兩個數據源都必須存在相同的值,即兩個數據源都必須存在知足聯接關係的元素。相似於SQL語句中的inner join子句。

分組聯接:包含into子句的join子句。

左外部聯接:元素的連接關係必須知足聯接中的左數據源,相似於SQL語句中的left join子句。

 

內部鏈接示例:

int[] arra = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

             int[] arrb = new int[] { 0, 2, 4, 6, 8 };

             var query = from a in arra

                        where a < 7

                        join b in arrb on a equals b

                        select a;

課程6  委託、匿名方法、Lambda表達式、LINQ查詢表達式

上課日誌2

補充—VS中自定義C#快速簡寫代碼(輸入簡寫字母后按兩次Tab鍵自動輸入

VS中選擇工具——>代碼段管理器(語言下拉框選擇Visual C#以下圖1所示),位置下面的下拉列表框再選擇Visual C#而後複製位置文本框裏的路徑即找到代碼段簡寫文件(*.snippet)。

而後隨便複製一個(好比cw.snippet)複製的位置能夠任意(注意兩點第1、不要在原來的cw.snippet位置,第2、須要新建一個文件夾zdy)來存儲複製過來cw.snippet文件

而後再對複製過來的文件修改(好比須要建立快速輸入Console.ReadKey(),能夠把文件名改成crk.snippet),接着打開重命名後的文件crk.snippet)修改裏面的內容(如2所示),參照3進行修改修改綠色框住的4個地方便可

最後單擊1下面的添加按鈕,選擇到自定義的文件夾zdy)。

 

1

 

2

 

3

2、泛型委託Func<T>

Fun<T>——Func委託只有泛型版本的,接受參數個數能夠是若干個,也能夠是沒有參數,可是必定有返回值的方法

Func<TResult>這個表示沒有參數,只有返回值的

Func<T,TResult>這個表示有1個參數,有返回值的

Func<T1,T2,TResult>這個表示有2個參數(前兩個參數T1,T2表示參數,最後TResult返回值),有返回值的

Func<T1,T2,T3,TResult>這個表示有3個參數(前三個參數T1,T2,T3,表示參數,最後TResult返回值),有返回值的.

總之Func委託最後一個TResult表示返回值,前面的無論多少個T都是表示參數

例:

class Program

    {

        static void Main(string[] args)

        {

            #region 無參數有返回值的Fun委託

            Func<int> fun1 = M1;

            int n1 = fun1();

            Console.WriteLine(n1);

            #endregion

 

            #region 有參數有返回值的Fun委託

            Func<int, int, int, int> fun2 = M2;

            int n2 = fun2(1, 2, 3);

            Console.WriteLine(n2);

            #endregion           

            Console.ReadKey();

        }

        static int M1()

        {

            return 1;

        }

        static int M2(int n1, int n2, int n3)

        {

            return n1 + n2 + n3;

        }

}

3、多播委託

多播委託就是一個委託同時綁定多個方法多播委託也叫委託鏈、委託組合

一、綁定無返回值的多個委託

class Program

    {

        static void Main(string[] args)

        {

            #region 綁定無返回值的多個委託

            Action<string> action = M1;//這句話只綁定一個M1方法(綁定第一個方法不能用+=複製,由於開始actionnull,因此只能用=賦值),下面再給acion綁定方法

            action += M2;

            action += M3;

            action += M4;

            action += M5;

            action -= M3;//解除綁定M3方法(便是用-=賦值爲解除綁定方法)

            action("多播委託");

            #endregion           

            Console.ReadKey();

        }

        static void M1(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M2(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M3(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M4(string msg)

        {

            Console.WriteLine(msg);

        }

        static void M5(string msg)

        {

            Console.WriteLine(msg);

        }

}

二、綁定返回值的多個委託如何獲取到每一個方法的返回值

class Program

    {

        static void Main(string[] args)

        {

            #region 綁定有返回值的多個委託

            Func<string, string> fc = T1;

            fc += T2;

            fc += T3;

           string result= fc("有參數有返回值的多播委託");

           Delegate[] delegates = fc.GetInvocationList();//按照調用順序返回此多播委託的調列表。便是有幾個方法就有個幾個委託,返回值爲Delegate數組

           for (int i = 0; i < delegates.Length; i++)//循環遍歷Delegate數組便可獲得每一個委託對象.這樣就能夠逐個委託調用,若是有返回值,能夠逐個拿到

           {

               //delegates[i](「……」);這句不行,由於Delegate是抽象類,因此不能直接調用,須要強轉爲子類                //(delegates[i] as Func<string,string>)();//沒有返回值就這樣就能夠,若是有返回值相似下一行代碼就能夠

               string s = (delegates[i] as Func<string, string>)("獲取多播委託每一個方法的返回值");

               Console.WriteLine(s);

           }

            #endregion

            Console.ReadKey();

        }

        static string T1(string msg)

        {

            return msg+"1";

        }

        static string T2(string msg)

        {

            return msg + "2";

        }

        static string T3(string msg)

        {

            return msg + "3";

        }

}

4、匿名方法

一、匿名類

static void Main(string[] args)

        {

            #region 匿名類

            var Anon = new { Name = "小明", Age = 3, Sex = '' };

            Console.WriteLine("個人名字是:{0},性別爲{1},年齡是{2}", Anon.Name, Anon.Sex, Anon.Age);

            Console.ReadKey();

            #endregion

        }

二、匿名方法

 匿名方法,便是沒有名字的方法,不能直接在類中定義,而是在給委託變量賦值的時候,須要賦值一個方法,此時能夠「現作現賣」,定義一個匿名方法傳遞給該委託。

匿名方法關鍵字delegate,delegate後的括號寫方法參數,{ }裏面寫方法體,這是一個賦值語句因此最後須要分號

1:

  #region 匿名方法無參數無返回值

            //若是存在一個已定義好的M1方法,則直接能夠把該方法賦給委託變量md 

           // Action md = M1; 

            //若是不存在已定義好的方法,則可使用匿名方法賦給委託變量,即現定義一個方法給委託變量

            Action  md = delegate()

            {

                Console.WriteLine("ok");

            };

            md();//調用匿名方法

            Console.ReadKey();

            #endregion

  static void M1()

        {

            Console.WriteLine("ok");

        }

2:

#region 有參數無返回值的匿名方法

            Action<string> md2 = delegate(string msg)

            {

                Console.WriteLine("Hello" + msg);

            };

            md2("你們好!");

            Console.ReadKey();

            #endregion

3:

#region 有參數有返回值的匿名方法

            Func<int,int,int,int> ad = delegate(int n1, int n2, int n3)//提問:這裏若是不採用匿名方法怎麼寫

            {

                return n1 + n2 + n3;

            };

            int result = ad(12, 10, 8);

            Console.WriteLine(result);

            Console.ReadKey();

            #endregion

5、Lambda表達式

一、Lambda介紹

「Lambda 表達式」(lambda expression)就是一個匿名函數(匿名方法),Lambda表達式基於數學中的λ演算得名。

  Lambda運算符:全部的lambda表達式都是用新的lambda運算符 " => ",能夠叫他:「轉到」或者 「成爲」,讀做 「goes to」。運算符將表達式分爲兩部分,左邊指定輸入參數右邊是lambda的主體(方法體)

        lambda表達式:

             一個參數:param=>expr

            多個參數:(param-list)=>expr

二、輸入參數與表達式或語句塊

輸入參數:在Lambda表達式中,輸入參數是Lambda運算符的左邊部分。它包含參數的數量能夠爲0、1或者多個。只有當輸入參數爲1時Lambda表達式左邊的一對小括弧才能夠省略。輸入參數的數量大於或者等於2時,Lambda表達式左邊的一對小括弧中的多個參數之間使用逗號(,)分割

表達式或語句塊:多個Lambda表達式能夠構成Lambda語句塊。語句塊是放到運算符的右邊,做爲Lambda的主體。語句塊中能夠包含多條語句,而且能夠包含循環、方法調用和if語句等。語句塊必須被"{"和"}"包圍。

 

1:無參數、表達式

#region 參數

//Action a = () => { Console.WriteLine("This is a Lambda expression."); };

Action a= ()=>Console.WriteLine("This is a Lambda expression.");

          a();

Console.ReadKey();

  #endregion

因爲上述Lambda表達式的輸入參數的數量爲0,所以,該Lambda表達式的左邊部分的一對小括弧不能被省略。右邊是一個表達式

 

2:1個參數狀況、語句塊

  #region 1個參數

            Action<int> b = m => { int n = m * 2; Console.WriteLine(n); };//此處參數m的括號能夠省略

            b(2);

#endregion

上述Lambda表達式的輸入參數省略了一對小括弧,它與「(m)=> { int n = m * 2; Console.WriteLine(n); };是等效的。右邊是語句塊,那麼該語句塊必須被"{"和"}"包圍,還有return語句不能省略花括號

 

3:多個參數、語句塊

  #region 多個參數

  Action<int,int> c = (m,n) => { int s = m * n; Console.WriteLine(s); };//此處參數的括號不能省略

            c(2,3);

#endregion

6、匿名方法、Lambda表達式應用鞏固舉例

1、匿名方法與Lambda的替

static void Main(string[] args)

        {

            //Func<int, int, int, int> ad = M2;

            #region 有參數有返回值的匿名方法

            Func<int, int, int, int> ad = delegate(int n1, int n2, int n3)//該匿名方法實際上與下面的有名方法M2同樣

            {

                return n1 + n2 + n3;

            };

            int result = ad(12, 10, 8);

            Console.WriteLine(result);

            #endregion

 

            #region 有參數有返回值的lambda表達式

            Func<int, int, int, int> ad2 = (x, y, z) => { return x + y + z; };

            int r = ad2(10, 20, 30);

            Console.WriteLine(r);

            #endregion

            Console.ReadKey();

        }

        static int M2(int n1, int n2, int n3)

        {

            return n1 + n2 + n3;

        }

說明:匿名方法、lambda表達式運行時最終都會編譯成方法

2定義一個能接收參數個數可變有返回值的委託

public delegate int Adddelegate(params int[] arr);//定義一個能接收參數個數可變且有返回值的委託

static void Main(string[] args)

        {

            #region 接收參數個數可變的lambda表達式

            Adddelegate ad = (arr) =>

            {

                for (int i = 0; i < arr.Length; i++)

                {

                    Console.WriteLine(arr[i]);

                }

                return arr.Sum();

            };

            int x = ad(1, 2, 3, 4, 5);

            Console.WriteLine(x);

            Console.ReadKey();

            #endregion

        }

3lambda表達式在泛型集合中的應用

示例:打印出泛型集合中大於6的元素。

static void Main(string[] args)

        {

List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 89, 10, 11, 12, 13, 14, 15 };

           //第一種寫法本身定義方法

            IEnumerable<int> ie = list.Where(cs); //var

            //第二種寫法用匿名方法

            //IEnumerable<int> ie = list.Where(delegate(int n)

            //{

            //    return n > 6;

            //}

            //    );//where裏面須要一個方法做爲參數(有1int類型參數,返回值爲bool類型)           

            //第三種寫法使用lambda表達式

            //IEnumerable<int> ie = list.Where(n => { return n > 6; });

            foreach (var item in ie)

            {

                Console.WriteLine(item);

            }

            Console.ReadKey();

           #endregion

        }

        static bool cs(int n)

        {

            return n > 6;

        }

7、Linq簡介

LINQ的全稱是Language Integrated Query,中文譯成「語言集成查詢」。LINQ一種查詢技術,LINQ to SQL、LINQ to Object、LINQ to ADO.NET、LINQ to XMLLINQ to EF等

LINQ與直接SQL語句比較:

1)SQL數據庫技術是一門相對比較複雜深奧的技術,不是人人都懂,而LINQ To SQL比較簡單(實際上底層都對數據庫操做進行了封裝,架構了數據訪問層)

2)直接寫SQL語句,若是有問題,只有到運行時才知道

3)LINQ To SQL能夠很好的防止注入式攻擊

4)Linq是面向對象的查詢,主要在程序內部使用(好比查找所需的數據),比使用DataReader讀取數據等方便多了;直接SQL是面向關係型數據庫的查詢

5)從運行效率上來講性能不如直接SQL語句,可是開發效率提升了。

要學習LINQ首先就要學習LINQ查詢表達式。

LINQ的查詢由3基本部分組成:獲取數據源,建立查詢,執行查詢。

// 1.獲取數據源

            List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            // 2.建立查詢

            var numQuery = from num in numbers

                           where num % 2 == 0

                           select num*10;

//SQL語句比較下

//string ql=」select StuName from Student where ID>1」

            // 3.執行查詢

            foreach (var num in numQuery)

            {

                Console.WriteLine(num);

           }

LINQ 中,查詢的執行與查詢自己大相徑庭;換句話說,若是隻是建立查詢變量,則不會檢索任何數據。

Linq的數據源要求必須實現IEnumerable或IEnumerable<T>接口,數組隱式支持這個接口numQuery叫作查詢變量,它存儲了一個查詢表達式。注意,聲明查詢變量並不會執行查詢,真正的執行查詢延遲到了foreach語句中

查詢表達式必須以from子句開頭,以select或group子句結束。第一個from子句和最後一個select子句或group子句之間,能夠包含一個或多個where子句、let子句、join子   句、orderby子句和group子句,甚至還能夠是from子句。它包括8個基本子句,具體說明以下所示。

●from子句:指定查詢操做的數據源和範圍變量。

●select子句:指定查詢結果的類型和表現形式。

●where子句:指定篩選元素的邏輯條件。

●let子句:引入用來臨時保存查詢表達式中的子表達式結果的範圍變量。

●orderby子句:對查詢結果進行排序操做,包括升序和降序。

●group子句:對查詢結果進行分組。

●into子句:提供一個臨時標識符。join子句、group子句或select子句能夠經過該標識符引用查詢操做中的結果。

●join子句:鏈接多個用於查詢操做的數據源。

8、Form子句

建立一個LINQ表達式必需要以from子句開頭。

1:單個Form子句

string[] values = { "中國", "日本", "美國", "菲律賓", "越南" };

            //查詢包含「國」的字符串

// IndexOf查詢參數字符串在父串中首次出現的位置,沒有返回-1

            var valueQuery = from v in values

                             where v.IndexOf("") > 0

                             select v;

            foreach (var v in valueQuery)

            {

                Console.WriteLine(v);

            }

            Console.ReadKey();

在這個LINQ表達式的from子句中,v叫作範圍變量,values是數據源。v的做用域存在於當前的LINQ表達式,表達式之外不能訪問這個變量。where用來篩選元素,select用於輸出元素。這裏的範圍變量v和foreach語句中隱式變量v均可以由編譯器推斷出其類型

2:複合Form子句

在查詢數據源中,元素的屬性是一個集合時,可使用複合from子句對這個屬性集合查詢。好比,一個客戶,可能有多個電話。

class CustomerInfo

    {

        public string Name { get; set; }

        public int Age { get; set; }

        public List<string> TelTable { get; set; }

    }

static void Main(string[] args)

        {

            formExpDemo();

            Console.ReadKey();

        }

        static void formExpDemo()

        {

            List<CustomerInfo> customers = new List<CustomerInfo> {

                                           new CustomerInfo{ Name="歐陽曉曉", Age=35, TelTable=new List<string>{"1330708****","1330709****"}},

                                           new CustomerInfo{ Name="上官飄飄", Age=17, TelTable=new List<string>{"1592842****","1592843****"}},

                                           new CustomerInfo{ Name="諸葛菲菲", Age=23, TelTable=new List<string>{"1380524****","1380525****"}}

                                           };

            //查詢包含電話號碼1592842****的客戶

            var query = from CustomerInfo ci in customers//ci

                        from tel in ci.TelTable

                        where tel.IndexOf("1592842****") > -1

                        select ci;

 

            foreach (var ci in query)

            {

                Console.WriteLine("姓名:{0} 年齡:{1}", ci.Name, ci.Age);

                foreach (var tel in ci.TelTable)

                {

                    Console.WriteLine("          電話:{0}", tel);

                }

            }

}

9、where子句select子句

1where子句

where子句的做用就是篩選元素,除了開始和結束位置,where子句幾乎能夠出如今LINQ表達式的任意位置。一個LINQ表達式中能夠有where子句,也能夠沒有;能夠有一個,能夠有多個;多個where子句之間的關係至關於邏輯「與」,每一個where子句能夠包含1個或多個邏輯表達式,這些條件成爲「謂詞」,多個謂詞之間用布爾運算符隔開,好比邏輯「與」用&&,邏輯「或」用||,而不是用SQL中的AND或OR。

class CustomerInfo

    {

        public string Name { get; set; }

        public int Age { get; set; }

        public string Tel { get; set; }

    }

List<CustomerInfo> clist = new List<CustomerInfo> {

new CustomerInfo{ Name="歐陽曉曉", Age=35, Tel ="1330708****"},

new CustomerInfo{ Name="上官飄飄", Age=17, Tel ="1592842****"},

new CustomerInfo{ Name="令狐沖", Age=23, Tel ="1380524****"}

                                                   };

            //查詢名字是3個字或者姓「令」的,但年齡大於20的客戶

            var query = from customer in clist

                        where (customer.Name.Length == 3 || customer.Name.Substring(0, 1) == "") && customer.Age > 20

                        select customer;

            foreach (var ci in query)

            {

                Console.WriteLine("姓名:{0} 年齡:{1} 電話:{2}", ci.Name, ci.Age, ci.Tel);

            }

2select子句

1:最簡單的select就是直接輸出from子句創建的那個範圍變量:

#region 簡單的select示例

            int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        select n;  //select n*10;對象.屬性

     #endregion

2:對查詢結果進行投影(轉換)。下面查詢表達式查詢arr數組中的每個元素,查詢結果轉換爲一個集合對象兩個屬性ID和Name,它在select子句中由匿名對象初始化器建立。每個對象的ID屬性的值是當前元素的值、Name屬性的值爲元素的值的字符串的表現形式。

#region 對查詢結果進行投影(轉換)

            int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var query = from n in arr

                        select new

                        {

                            ID = n,

                            Name = n.ToString()

                        };

            foreach (var item in query)

            {

                Console.WriteLine(item.ID+"  "+item.Name);

            }

            Console.ReadKey();

 #endregion

 

10、Group子句into子句orderby子句

1Group子句

LINQ表達式必須以from子句開頭,以select或group子句結束,因此除了使用select子句外,也可使用guoup子句來返回元素分組後的結果。group子句用來將查詢結果分組,並返回一對象序列。這些對象包含零個或更多個與該組的key值匹配的項。

注意:每個分組都不是單個元素,而是一個序列(也屬於集合)。序列的元素類型爲IGrouping<TKey,TElement>(必須Group子句結束的LINQ表達式,分組結果類型才爲序列序列的元素類型爲IGrouping<TKey,TElement>)

List<CustomerInfo> clist = new List<CustomerInfo> {

  new CustomerInfo{ Name="歐陽曉曉", Age=35, Tel ="1330708****"},

  new

相關文章
相關標籤/搜索