2013-07-27 32 views
6

我有一個接口,這樣的...Resharper,「返回類型可以IEnumerable ...」但爲什麼?

public interface IAccountRepository : IDisposable { 
    IQueryable<Account> FindByUserId(int userId); //here, Resharper says "Return type can be IEnumerable<Account>" 
} 

但ReSharper的是在暗示我將其更改爲IEnumerable<Account> FindByUserId(int userId)代替。

這是爲什麼?它不會強制整個對象被加載到內存中嗎?我認爲推遲執行直到真正需要對象纔會更好?

+3

例如,直到執行諸如'.Count()'或'.ToList()'等方法,纔會將其加載到內存中。 –

+0

這將是因爲你的解決方案沒有在'FindByUserId'返回的對象上使用任何'IQueryable '方法,所以R#建議你可以使返回類型更一般化。 – porges

+1

@ Pierre-LucPineault IQueryable允許在不預先將結果加載到內存中的對象的情況下進一步細化查詢('.Where ...')。顯然這不是IEnumerable的情況吧? –

回答

8

這是一般規則的只是一個特定實例。

如果您要返回的類型爲SomeClass,它實現了一個接口或從另一個類繼承,並且在整個解決方案中,您只使用基類/接口中返回的對象上的方法(因此您不使用任何方法在SomeClass中聲明),ReSharper會建議你將返回的對象的類型替換爲基類/接口的類型,以使代碼更一般化。

在這種情況下,您只使用IQueryable<T>派生自的IEnumerable<T>接口的方法。

還請注意,這只是一個建議,而不是一個警告或錯誤。如果你願意,你可以放心地忽略這個。

+3

+1 *返回類型可以是'IEnumerable' *只是意味着返回類型*可以*是' IEnumerable'不是它*應該*。 –

+1

謝謝..我只是想確保我明白我在做什麼,而不是盲目地遵循R#建議。 –

1

IQueryable已從IEnumerableMSDN)繼承,因此您對IEnumerable的任何異議仍將存在。 ReSharper的是表明該方法可能也被定義爲返回IEnumerable即使全部實現返回IQueryable(如果呼叫需要一個IQueryable而不是IEnumerable,他們可以叫AsQueryableMSDN

也是一個IEnumerable的成員只能當它們被枚舉時被檢索,這意味着例如即使每個成員是通過單獨的Web服務調用獲得的,這些調用也只會在請求特定成員時纔會發生。

+1

從我的理解,他們的行爲不同,看到這個答案︰http://stackoverflow.com/a/2876655/193634 –

6

答案是 「沒有,」。

它鑄造於IEnumerable的不強制執行。 IEnumerable空間中的運算符(如「Where」方法)仍然可以進行懶惰評估。

但這裏是一些警告。如果你在這個方法中開始使用LINQ操作符,那麼LINQ將選擇可枚舉的LINQ操作符,如GroupBy (IEnumerable)而不是Queryable操作符,如GroupBy (IQueryable)。注意他們的參數列表不同。

這樣做的效果是,您傳遞的Lambda表達式將轉換爲Func而不是Expression>(注意兩個方法的參數列表中的差異)。所以你的lambda不會是一個表達式樹,這是Queryable源爲了將它翻譯成SQL(或類似的)所需要的,以便查詢可以通過服務器傳遞並執行服務器端。

所以,你的查詢會比較慢。不是因爲它會在你投射它之後執行,而是因爲一旦你開始嘗試從中刪除項目,整個數據源將被拖到客戶端。

這當然只有在這個方法內部開始使用LINQ(附加「Where」子句或者其他)。如果你不這樣做,你很好。

+0

這意味着我可能會瘋狂地將大量的結果轉移到內存中進行過濾嗎?這是我從這個答案瞭解,http://stackoverflow.com/a/2876655/193634 –

+1

您在此方法中使用的任何LINQ操作符將無法執行服務器端。 – Tormod

+0

@RosdiKasim如果你從你的倉庫中返回瘋狂的大數據集,那麼你可能會這樣做嗎? 「IQueryable」是一個漏洞抽象,如果有的話,所以你想盡可能早地限制結果集,只處理服務層中的IEnumerable。 – kai

相關問題