2012-01-20 43 views
4

我知道String擴展方法返回一個String並且實際上並不影響調用該擴展方法的變量(因此它是不可變的) - 但是如何判斷其他擴展方法是否執行?例如,我有List<NewsItem>工作 - 我需要訂購該按日期列出降下來,所以我寫了這個代碼:如何判斷擴展方法是否影響「this」?

newsItems.OrderByDescending(o => o.Date); 

這是否會影響newsItems列表或只是返回IOrderedEnumerable ??

換言之,應該在上面的代碼實際讀:

newsItems = newsItems.OrderByDescending(o => o.Date).ToList(); 

??

感謝,

+0

你可以真正地測試他自己你知道...只需在列表中放入3個數字,看看他們是否被排序。 – Tudor

+0

我的問題是你怎麼知道?每次我想知道擴展方法是否有這種效果時,似乎沒有必要運行這樣的測試。 –

+0

字符串擴展方法不能更改字符串,因爲字符串是不可變的。 –

回答

4

OrderByDescendingIEnumerable<T>上的擴展方法,它本身提供了只讀的訪問權限。當然,擴展方法可以將轉換爲List<T>,但基本上沒有任何LINQ to Objects擴展方法影響其目標(假設目標不受迭代影響,當然)。

LINQ被設計成函數樣式 - 方法返回數據的新視圖,而不是改變它們被調用的目標。

編輯:正如提請注意的那樣,[Pure]屬性可以用來指示這一點,並且一些工具會接受它。但是:

  • 你仍然需要相信,[Pure]屬性已經被正確地應用
  • 這並不總是很容易分辨是否有一個[Pure]屬性(它不會在文檔中顯示我掛,例如)
  • 或許你也應該閱讀什麼的文檔,你打電話呢,如果你不是在它做什麼
+0

謝謝喬恩。我碰巧知道關於字符串的一些知識,現在關於LINQ擴展 - 這只是一個經驗案例(知道什麼擴展會影響他們的目標),還是有一種方法可以查看擴展方法,以便能夠告訴?? –

+1

@DanielMcNulty:你閱讀文檔,基本上 - 這裏的擴展方法和其他方法沒什麼不同。如果你打算打電話,你應該明白它會做什麼,通常包括閱讀文檔。 –

+0

非常感謝喬恩,這就是我所追求的 - 關於它是否僅僅是一種從經驗和文檔中知道我正在使用的案例的澄清 - 而且這是公平的。再次感謝。 –

2

所有的LINQ的擴展方法只對序列進行查詢操作,所以假定他們只讀(查詢)。因此,他們返回提供表示操作結果的值序列的實例。

當然,沒有什麼能阻止你制定一個擴展方法來修改它所應用的對象(this)。

然而,API包含的元數據在這種情況下很有用。 PureAttribute屬性可用於沒有副作用的方法。如果您在IDE中使用諸如ReSharper之類的工具,那麼當您嘗試調用純方法並且不使用結果時,它會發出警告。因爲這種方法是純粹的,所以它在記憶中沒有其他地方存在可見的副作用,所以忽略結果有點愚蠢。 Linq運算符用這個屬性註釋。舉例來說,它就是object.ToString()。你也可以在你自己的代碼中使用這個屬性。

tl; dr R#在這種情況下會發現你的bug。

0

一般由參數(值O型信心r引用類型),其次是返回類型。

如果您有一個方法簽名,例如DateTime DateTime.AddDays(int days),您會得到兩個提示:該方法不會影響原始日期時間 - 首先,DateTime是值類型,其次是返回DateTime。值類型(如果在方法體中進行了修改)只會將其更改本地應用於堆棧上的副本。除非返回值類型,否則調用方將無法觀察這些更改。相比之下,參考類型可以在調用方法中進行修改,並且可以調用者觀察到的修改。

同樣,如果你有一個方法,如IOrderedEnumerable<T> OrderBy(IEnumerable<T> enumerable),儘管事實上輸入類型是一個引用類型(並且可以修改),但提示是當返回一個新類型時,原始數據將保持不變。

最後,這可以通過測試來確認。作爲興趣點一般的LINQ方法鏈擴展方法都返回一個新IEnumerable<T>,是懶惰的評估,不修改IEnumerable<T>傳遞的內容,而不是應用時GetEnumerator被稱爲在返回其評估過濾IEnumerable<T>.

相關問題