更新:你有固定的標題,所以忽略了咆哮。
你的問題的標題無關,與你的代碼示例。你的問題意味着一種語法是IEnumerable,另一種是IQueryable,但這是不正確的。在您的樣品,如果db.Surveys
是一個IQueryable,然後都您的樣品使用IQueryable的。我會盡量回答這兩個問題都是。
你的兩個代碼示例是編寫相同的LINQ查詢(假設他們是寫得很好),只是方式不同。示例1中的代碼只是示例2中代碼的簡寫。編譯器會以相同方式處理這兩個示例中的代碼。想想C#編譯器會如何處理int?
與Nullable<System.Int32>
相同。 C#和VB.Net語言都提供了這種簡寫查詢語法。其他語言可能沒有這種語法,您將不得不使用示例2語法。事實上,其他語言甚至可能不支持擴展方法或lambda表達式,並且還需要使用更加醜陋的語法。
更新:
爲了進一步採取Sander的例子,當你寫這個(查詢理解語法):
var surveyNames = from s in db.Surveys select s.Name
你認爲編譯器開啓的是簡寫成這個(擴展方法和λ表達):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
但實際上擴展方法和lambda表達式本身就是簡寫。編譯器發出這樣的事情(不完全,但只給一個想法):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
注意Select()
在Queryable
類只是一個靜態方法。如果您的.NET語言不支持查詢語法,lambdas或擴展方法,那麼您將不得不自己編寫代碼。
什麼是使用一種風格比其他的好處?
對於小的查詢,擴展方法可以更緊湊:
var items = source.Where(s => s > 5);
此外,擴展方法的語法可以更靈活,例如條件where子句:
var items = source.Where(s => s > 5);
if(smallerThanThen)
items = items.Where(s => s < 10);
if(even)
items = items.Where(s => (s % 2) == 0);
return items.OrderBy(s => s);
另外,只有通過擴展方法語法(Count(),Aggregate(),Take(),Skip(),ToList(),ToArray()等)才能使用幾種方法,所以如果我使用其中的一種方法,通常會以這種語法編寫整個查詢以避免混合b其他語法。
var floridaCount = source.Count(s => s.State == "FL");
var items = source
.Where(s => s > 5)
.Skip(5)
.Take(3)
.ToList();
在另一方面,當查詢變得更大,更復雜,查詢綜合語法可以更清晰,特別是一旦你開始與一些let
,group
,join
複雜等
在結束我通常會爲每個特定的查詢使用更好的作品。
更新:您固定您的標題,所以忽略休息...
現在,關於你的標題:關於LINQ,IEnumerable和IQueryable的非常相似。它們都有幾乎相同的擴展方法(Select,Where,Count等),主要的區別在於IEnumerable以Func<TIn,TOut>
作爲參數,IQueryable以Expression<Func<TIn,TOut>>
作爲參數。你用同樣的方式表達(通常是lamba表達式),但在內部它們完全不同。
IEnumerable是LINQ to Objects的入口。可以在任何IEnumerable(數組,列表,任何可以迭代的東西)上調用LINQ to Objects擴展方法,並且Func<TIn,TOut>
在編譯時轉換爲IL,並在運行時像普通方法代碼一樣運行。請注意,其他一些LINQ提供程序使用IEnumerable,因此實際上在後臺使用LINQ to Objects(LINQ to XML,LINQ to DataSet)。
IQueryable的是使用LINQ到SQL,LINQ到需要檢查你的查詢,而是把它翻譯直接執行代碼的實體,和其他LINQ提供程序。在編譯時,IQueryable查詢及其Expression<Func<TIn,TOut>>
不會編譯爲IL。而是創建一個表達式樹,並可以在運行時檢查。這允許將語句翻譯成其他查詢語言(例如T-SQL)。表達式樹可以在運行時編譯成Func < TIn,TOut >,並在需要時執行。
可以在this question中找到一個示例,其中OP想要在SQL Server中執行LINQ to SQL查詢的一部分,將對象轉換爲託管代碼,並將LINQ to query中的其餘查詢。爲了實現這一點,他所要做的就是將IQueryable投入到他希望切換髮生的IEnumerable中。
其值得一提的樣品是不相同...... – 2009-04-28 04:43:55
另外,.ToList()結尾的力量相當不同的執行。第一個x是IQueryable類型,第二個是IList 。 –
2010-06-03 18:36:43