亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解LINQ入門(中篇)

 更新時間:2019年12月16日 09:46:30   作者:森大科技  
這篇文章主要介紹了詳解LINQ入門(中篇),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前 言

上篇中簡單的分享了LINQ的基礎(chǔ)概念及基礎(chǔ)語法,如果沒有閱讀過上篇的朋友可以點擊這里。感謝大家的支持,本篇我們將更進一步的學習LINQ的一些相關(guān)特性及應用方法。廢話不多說,請往下閱讀吧。

延遲加載

在上篇中簡單的和大家提到了LINQ具有一個很有意思的特性那就是“延遲加載”(或“延遲計算”),什么是延遲加載呢?先看來自官方的描述:延遲執(zhí)行意味著表達式的計算延遲,直到真正需要它的實現(xiàn)值為止。是不是覺得有點生澀難理解呢?按照我個人的理解通俗的講就是,每當我們編寫好一段LINQ表達式時,此時這個表達式所代表的序列變量僅僅只是一個代理,編譯器在執(zhí)行編譯時根本就不鳥這段代碼,檢查完語法正確性后直接跳過,直到代碼在編譯器動態(tài)運行序列變量在其他代碼塊被調(diào)用時,它所代理的linq表達式才會執(zhí)行。啊~~看到這里你是不是要暈了,到底要怎么理解啊,無廢話上代碼:

// 已知一個序列
var array = new int[] {1, 2, 3};

// 編寫一段LINQ表達式獲得一個序列變量query
// 注意,這個變量僅僅是一個代理,在執(zhí)行編譯的時候,編譯器檢查完
// 該代碼的正確性后直接跳過,不再理會
var query = from arr in array
      where arr > 1
      select arr;

// 調(diào)用上述序列變量query,此時上述的LINQ表達才會執(zhí)行。注意此時已是在
// 編譯器Runtime 的情況下執(zhí)行
foreach(var q in query)
  Console.WriteLine(q.ToString());

如果你覺得上述例子不能讓你有個深刻的理解,那么請看來自MSDN的例子

public static class LocalExtensions
{
  public static IEnumerable<string>
   ConvertCollectionToUpperCase(this IEnumerable<string> source)
  {
    foreach (string str in source)
    {
      Console.WriteLine("ToUpper: source {0}", str);
      yield return str.ToUpper();
    }
  }
}

class Program
{
  static void Main(string[] args)
  {
    string[] stringArray = { "abc", "def", "ghi" };
    // 這里方法 ConvertCollectionToUpperCase 是不會在編譯時進行調(diào)用核查的,直到下面的foreach調(diào)用變量 q 此方法才會執(zhí)行
    var q = from str in stringArray.ConvertCollectionToUpperCase()
        select str;

    foreach (string str in q)
      Console.WriteLine("Main: str {0}", str);
  }
  }

注意,ConvertCollectionToUpperCase 是一個靜態(tài)擴展方法,后續(xù)講解,如果你對.net 2.0 的 yeild 不熟悉的網(wǎng)上查閱吧,這里就不做介紹了。

// 輸出結(jié)果

// ToUpper: source abc

// Main: str ABC

// ToUpper: source def

// Main: str DEF

// ToUpper: source ghi

// Main: str GHI

小結(jié),延遲加載有好也有壞,由于是在Runtime的情況下執(zhí)行序列,所以就容易造成未知異常,斷點打錯等等,所以編碼LINQ是一定要考慮到它的這個特性。

lambda 表達式

了解完延遲加載后,那么現(xiàn)在我們需要簡單的學習一下.net 3.5 給我們帶來的新特性lambda表達式,在上篇的評論中,有園友問lambda和linq有什么關(guān)系,在這里其實他們沒有任何關(guān)系,是完全不同的東西,但是我們?yōu)槭裁匆莆账兀恳驗樵诤罄m(xù)的學習中會使用大量的lambda表達,他可以使我們的代碼更優(yōu)雅更有可讀性,大大提高了我們的編碼效率。

那么在學習lambda之前,先來回顧一下.net 2.0給我們帶來的委托 delegate ,這個你一定不會感到陌生吧,而且一定會常用他。對于委托這里就不做詳細的介紹了,要復習委托的在網(wǎng)上查閱吧。通過委托,我們可以得到一個東西“匿名方法”。咦,是不是覺得很眼熟,呵呵,用代碼來加深回憶吧

public delegate void SomeDelegate1;
public delegate void SomeDelegate2(arg 1, arg 2);

// 匿名方法
SomeDelegate1 del1 += delegate() {...};
SomeDelegate2 del2 += delegate(arg1, arg2) {...}

上面的代碼中我們看到在.net 2.0時代,我們可以通過delegate創(chuàng)建匿名方法,提高編碼的靈活性,那么lambda和這個有什么關(guān)系呢,lambda對匿名方法進行了升華??创a:

public delegate void SomeDelegate1;
public delegate void SomeDelegate2(arg 1, arg 2);

// 匿名方法
SomeDelegate1 del1 += () => {...};
SomeDelegate2 del2 += (arg1, arg2) => {...}

呵呵,是不是覺得有點不可思議呢,言歸正傳什么是lambda表達式呢,來自官方的定義:“Lambda 表達式”是一個匿名函數(shù),它可以包含表達式和語句,并且可用于創(chuàng)建委托或表達式樹類型。所有 Lambda 表達式都使用 Lambda 運算符 =>,該運算符讀為“goes to”。 該 Lambda 運算符的左邊是輸入?yún)?shù)(如果有),右邊包含表達式或語句塊。 Lambda 表達式 x => x * x 讀作“x goes to x times x”。在定義里提到了表達式樹,這是高階晉級的話題,這里就不做討論了,我們先把精力放在入門與實戰(zhàn)應用上。

常規(guī)的lambda表達式如下:

(parameters) => { }

當指定的委托類型沒有參數(shù)是表達式可以如下

() => { } 例:() => {/*執(zhí)行某些方法*/}

如果表達右側(cè)花括號里只有一個表達例如一元表達式,二元表達式等等,又或者是一個方法時那么花括號可以省略如下:

 (x) => x; // 最簡表達式

 (x, y) => x == y;

 () => SomeMethod();

注意,如果右側(cè)的表達式存在花括號"{}",而且委托是具有返回類型的,那么表達式必須帶上 return 關(guān)鍵字,如下:

(x, y) => {return x == y;};

到此我們已對lambad 表達式有了一定的掌握與了解。那么我們擴展一下,在.net 3.5中,ms 給我們提供了兩個泛型委托 分別是 Fun<T> 和 Action <T> 他們可以幫助我們省去了返回創(chuàng)建常用委托的麻煩,提高編碼效率。

共同點:它們至多提供委托傳遞6個參數(shù)(任意類型);

不同點:Fun 要求必須具有返回類型,而Action則必須不返回類型,規(guī)定返回 void

示例:

Fun<int, int, bool> fun = (a, b) => a==b;
Action<string> action = (p) => Console.Write(p);

小結(jié),lambda 對我個人而言是個又愛又恨啊,不過愛多一點,它使我們寫更少的代碼做更多的事,但是在調(diào)試時一旦修改表達式內(nèi)容,那么當前調(diào)試要么停止,要么重新開始,ms要是在這方面做得更完美些就好啦。不過它也間接提醒我們要有好的編碼設(shè)計思維。

靜態(tài)擴展方法

說完lambda,那么我們就進一步了解一下.net 3.5的另一個新特性“靜態(tài)擴展方法”,什么是靜態(tài)擴展方法呢,官方定義:擴展方法使您能夠向現(xiàn)有類型“添加”方法,而無需創(chuàng)建新的派生類型、重新編譯或以其他方式修改原始類型。 擴展方法是一種特殊的靜態(tài)方法,但可以像擴展類型上的實例方法一樣進行調(diào)用。簡單的說就是我們可以向一個已知的類型在不通過繼承,復寫等操作的情況下添加一個方法,以便類型的實例可以直接使用該方法。示例如下:

static class A

{

  // 這里的p1,p2 僅作為示例,實際中我們不一定需要

  public static int ExtendMethod1(this string input,string p1, string p2)

  {

     return int.Parse(input + p1 + p2);

  }

 

   // 泛型方法

   public static TOutput, ExtendMethod2<TOutput>(this obj);

   {

      return (TOutput)obj;

   }

}

class B
{
  void Main()
  {
   var a = "1";
   var result = a.ExtendMethod1("2","3");
   // result:123
  }
}

注意,方法的 static 是必須的,而且需在靜態(tài)類里。第一個參數(shù) this 是必須的,緊跟著 this 后面的需要擴展的類型實例參數(shù),也是必須的。至于后面的方法調(diào)用傳遞參數(shù)就因個人所需了。

既然我們學習了靜態(tài)擴展方法,那么它和LINQ又有什么關(guān)系呢?在System.Linq的命名空間中提供了大量的靜態(tài)擴展方法,這些靜態(tài)方法本身就對linq表達式的封裝,這樣我們就可以省去了編寫簡單的linq表達式的步驟。如下:

var array = new int[]{1,2,3,4,5};

 

var query1 = from arr in array

       select arr;

 

var query2 = array.Select(e => e);

上面的示例中 query1 和 query2 是等價的,通過 query2 我們是不是又可以偷懶了很多,呵呵。

再來點帶where的

var array = new int[]{1,2,3,4,5};

 

var query1 = from arr in array

       where arr > 2

       select arr;

 

var query2 = array.Where(e => e > 2);

再來一個復合型的

var array = new int[]{1,2,3,4,5};

 

var max = (from arr in array.Where(e => e > 2)

      select arr).Max();

是不是覺得很cool。由于篇幅的關(guān)系在這里就不逐一的去接受這些靜態(tài)方法了,下面是一些常用的靜態(tài)方法列表,感興趣的去MSDN查閱詳細吧。

Aggregate , All , Any , AsEnumerable , Average , Cast , Concat , Contains, Count, DefaultIfEmpty , Distinct , ElementAt, ElementAtOrDefault ,Empty , Except , First, FirstOrDefault , GroupBy , GroupJoin , Intersect , Join , Last , LastOrDefault , LongCount , Max , Min , OfType ,OrderBy ,OrderByDescending , Range , Repeat , Reverse , Select , SelectMany , SequenceEqual , Single , SingleOrDefault , Skip , SkipWhile , Sum ,Take, TakeWhile , ThenBy , ThenByDescending , ToArray , ToDictionary , ToList, ToLookup, Union,Where

Cast<T> 和 OfType<T> 靜態(tài)擴展方法

在最后我們還是要注意兩個常用的靜態(tài)方法Cast<T>, OfType<T> 。它們的共同點是都能把非IEnumerable<T> 類型的集合轉(zhuǎn)換成IEnumerable<T>類型,然后再

進行LINQ操作,如下

var dt = new DataTable();
dt.Columsn.Add("A", typeof(int));

var newRow1 = dt.NewRow();
newRow1["A"] = 1;

var newRow2 = dt.NewRow();
newRow2["A"] = 2;

dt.Rows.Add(newRow1);
dt.Rows.Add(newRow2);

var query1 = dt.Rows.Cast<DataRow>().Select(e=>(int)e["A"]);
var query2 = dt.Rows.OfType<DataRow>().Select(e=>(int)e["A"]);

這樣我們就可以得到看上去兩個相同的序列,在這里要注意:MSDN上的說明存在誤導,MSDN對于OfType<T>的解釋存在偏差,實際上經(jīng)本人反復敲代碼驗證,得到的結(jié)論是,Cast對序列進行強制轉(zhuǎn)換,一旦轉(zhuǎn)換不成功則拋出異常。OfType則是一旦轉(zhuǎn)換不成功,則不會拋出異常,但是將會得到一個空序列。見下面代碼:

var arr1 = new string[] { "1","2","test" };
var arr2 = arr1.Cast<int>();
var arr3 = arr1.OfType<int>();

//通過Cast轉(zhuǎn)換,則會拋出異常
foreach (var i in arr2)
   Console.WriteLine(i.ToString());

//通過OfType轉(zhuǎn)換,有異常但是不會拋出并得到一個空序列
foreach (var i in arr3)
   Console.WriteLine(i.ToString());

Console.Read();

總 結(jié)

本文到此,我們已對LINQ涉及的應用有了進一步的了解。學習什么是linq的延遲加載,lambda和linq是否有曖昧關(guān)系。以及靜態(tài)擴展方法對linq的輔助作用。也許你會問既然可以用靜態(tài)擴展方法替代編寫linq,那么二者怎么擇取呢,據(jù)磚家叫獸提議我們應該先以linq命名空間下的靜態(tài)擴展方法為主,實在是很復雜的linq表達式,我們再考慮使用linq本身的表達式編寫。后續(xù)我們將分享學習LINQ更貼近實戰(zhàn)應用的知識,linq to dataset, linq to , linq to sql, linq to entities.

感謝您的閱讀,如果有說得不對的地方請指正。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#操作圖片讀取和存儲SQLserver實現(xiàn)代碼

    C#操作圖片讀取和存儲SQLserver實現(xiàn)代碼

    用C#將Image轉(zhuǎn)換成byte[]并插入數(shù)據(jù)庫/將圖片數(shù)據(jù)從SQLserver中取出來并顯示到pictureBox控件上,接下來將為你詳細介紹下實現(xiàn)步驟,感興趣的你可以參考下
    2013-03-03
  • Visual Studio C#創(chuàng)建windows服務程序

    Visual Studio C#創(chuàng)建windows服務程序

    用Visual C#創(chuàng)建Windows服務不是一件困難的事,本文就將指導你一步一步創(chuàng)建一個Windows服務并使用它,本文主要介紹了Visual Studio C#創(chuàng)建windows服務程序,感興趣的可以了解一下
    2024-01-01
  • 詳解DataGridView控件的數(shù)據(jù)綁定

    詳解DataGridView控件的數(shù)據(jù)綁定

    本文詳細講解了DataGridView控件的數(shù)據(jù)綁定,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • C#處理TCP數(shù)據(jù)的方法詳解

    C#處理TCP數(shù)據(jù)的方法詳解

    Tcp是一個面向連接的流數(shù)據(jù)傳輸協(xié)議,用人話說就是傳輸是一個已經(jīng)建立好連接的管道,數(shù)據(jù)都在管道里像流水一樣流淌到對端,那么數(shù)據(jù)必然存在幾個問題,比如數(shù)據(jù)如何持續(xù)的讀取,數(shù)據(jù)包的邊界等,本文給大家介紹了C#處理TCP數(shù)據(jù)的方法,需要的朋友可以參考下
    2024-06-06
  • C# lambda表達式應用如何找出元素在list中的索引

    C# lambda表達式應用如何找出元素在list中的索引

    這篇文章主要介紹了C# lambda表達式應用如何找出元素在list中的索引的相關(guān)資料,需要的朋友可以參考下
    2018-01-01
  • C#圖像識別 微信跳一跳機器人

    C#圖像識別 微信跳一跳機器人

    這篇文章主要為大家詳細介紹了C#圖像識別,微信跳一跳機器人,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C#刪除整個目錄及子目錄的方法

    C#刪除整個目錄及子目錄的方法

    這篇文章主要介紹了C#刪除整個目錄及子目錄的方法,涉及C#操作目錄刪除的相關(guān)技巧,需要的朋友可以參考下
    2015-04-04
  • C# yield在WCF中的錯誤使用(二)

    C# yield在WCF中的錯誤使用(二)

    這篇文章主要介紹了C# yield在WCF中的錯誤使用(二),本文講解的內(nèi)容據(jù)說是99%的開發(fā)人員都有可能犯的錯誤,需要的朋友可以參考下
    2015-04-04
  • C#調(diào)用SQLite的詳細代碼舉例

    C#調(diào)用SQLite的詳細代碼舉例

    SQLite是一個輕量級、跨平臺的關(guān)系型數(shù)據(jù)庫,在小型項目中,方便,易用,同時支持多種開發(fā)語言,這篇文章主要給大家介紹了關(guān)于C#調(diào)用SQLite的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • C# 設(shè)置防火墻的創(chuàng)建規(guī)則

    C# 設(shè)置防火墻的創(chuàng)建規(guī)則

    這篇文章主要介紹了C# 設(shè)置防火墻的創(chuàng)建規(guī)則,幫助大家更好的利用c#操作防火墻,感興趣的朋友可以了解下
    2020-11-11

最新評論