Linq系列(3)——Lambda 運算式,運算式樹狀架構

來源:互聯網
上載者:User

  在開始今天的內容之前,我現在這回答楊裕欣同學的一個問題。我在昨天的文章中說過一個很核心的問題,linq其實有2套東西,用於處理本機資料源的IEnumerable<T>和處理遠端資料源的IQueryable<T>。然後本機資料源可以直接代入方法的邏輯進行處理,而遠端資料源必須把方法的邏輯變成運算式樹狀架構,再把運算式樹狀架構中相應的元素剝離出來,變成遠端資料源可以識別的邏輯進行處理,遠端資料源要這麼做是因為沒有了.net運行時這個內容相關的支援,所以無法識別.net中的方法的邏輯。

      所以由此,就引出了楊裕欣同學的兩個問題:

      a.比如對於IEnumerable<Customer> customers; 
       Customer類有個屬性:IList<String> Addresses;
     var q = customers.Where(c => c.Addresses.Contain("xxxx"))
     是否ok
      b.如果把customers類型用AsQueryable函數轉成IQueryable<Customer> 又怎麼樣。。。

      先回答問題a.肯定可以,因為本機資料源,有.net運行時的支援,可以直接把Contain方法的邏輯代入進行篩選

      再來回答問題b.也可以,雖然AsQueryable使處理資料來源的方式變成了處理遠端資料源的方式,但同樣可以。為什嗎?ok,在回答為什麼之前,我們先來看看什麼情況下不行:

       所謂IQueryable這套東西無法處理的,實際就是無法變成運算式樹狀架構的,根據msdn的資料:

       http://msdn.microsoft.com/zh-cn/library/bb397687.aspx

       無法變成運算式樹狀架構的典型情況有兩種,一種是用了.net中的方法

       () => SomeMethod()

       一種用了lamabda語句:

       Lambda 語句與 Lambda 運算式類似,只是語句括在大括弧中: (input parameters) => {statement;}

   Lambda 語句的主體可以包含任意數量的語句;但是,實際上通常不會多於兩個或三個語句。
   TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };

       總結起來,這兩種情況無法變成運算式樹狀架構都是因為調用了.net中的方法。所以楊裕欣同學的問題就很好理解了——Contain不是也是.net中的方法嗎?為什麼用了Contain方法就可以變成運算式樹狀架構,調其他很多方法就不行呢?

      ok,這就引出了一個我們今天一定要講清楚的一個概念——Provider。

      我們再來分析一下產生運算式樹狀架構的這個過程,IQueryable中式靠什麼把我們運算式(類似item => item.Length>3)中的基本邏輯解析成運算式樹狀架構的?

      答案是——Provider,可以參考下msdn的資料:

       http://msdn.microsoft.com/zh-cn/library/bb882636.aspx

       現在問題就衍變成了為什麼有的方法Provider可以解析有的卻不能,我們能否找出Provider可以解析的方法的一個充要條件?

      要回答這個問題,我們先回答另一個問題:Linq是用來做什麼的?Linq是用來查詢關係型資料來源的,這方面內容的詳情請參考這篇文章http://www.cnblogs.com/Ivony/archive/2008/08/28/1278643.html

     簡而言之,Linq能處理的IEnumerable<T>,sql,xml都是關係型資料來源,而contain是定義在IEnumerable上的方法,相當於對關係的一種邏輯,所以Provider可以把它解析成運算式樹狀架構,再直接點,當IEnumerable<T>中的資料來源可以表示成一個關係時,它的方法就可以被解析成運算式樹狀架構。對於關係這個概念,非常推薦大家參考上面連結的Ivony的那篇文章,非常贊。

      接下來,我們來講今天剩下的一個重要的內容:Lambda運算式。

      我們先看一個普通的Lambda運算式:(x, y) => x == y。

  我們先來回答一個問題:Lambda運算式本質是什嗎?

      lambda 運算式是一種無名函數,用於計算並返回單個值。lambda 運算式可在委託類型有效任何地方使用。

      請大家注意:只有可以表示為關係的Lambda運算式才能變成運算式樹狀架構

      (x, y) => x == y 元素和元素的關係

       x => x.Length>4  元素和屬性的關係

      注意:沒有元素和方法的關係,要是調用了自訂的方法是無法產生合法的運算式樹狀架構的。

      或者我們這麼理解:構成關係的集合必須是狀態的集合。

      最後再強調下:Lambda運算式就是匿名方法,能變成運算式樹狀架構的Lamabda運算式是有限制的,Lambda語句無法變成運算式樹狀架構。

      說下下一篇的預告:Lambda運算式樹狀架構。

      話說這個系列已經寫了3篇了,這個系列不是講應用,主要想跟大家一起探討下Linq中一些原理和理論。希望目前的這幾篇文章能幫大家把以下知識點串起來:迭代器,IEnumerable,ICollection,IList之間的繼承關係,擴充方法,var,匿名函數,運算式,運算式樹狀架構,provider,linq中的2套東西(IEnumerable<T>和IQueryable<T>),關係。

      最後的最後連結下楊裕欣童鞋的blog:http://www.cnblogs.com/yayx/

     

 

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.