2013-04-28 40 views
2

我最近開始使用ReSharper。什麼時候應該將集合上的循環轉換爲Linq語句?

ReSharper建議將集合上的所有循環(通常爲foreach)轉換爲Linq語句,即使循環包含各種條件也是如此。

  • 這會提高性能嗎?
  • 這是否使代碼更具可讀性?

一般來說,我應該在什麼時候遵循ReSharper關於這個問題的建議,以及什麼時候不應該?

+0

這太模糊了,無法給出具體的答案。你*以後認爲代碼更具可讀性嗎?總是,還是有時? – 2013-04-28 16:33:05

+0

@Jon,有時我覺得它更具可讀性。但大多數時候(通常涉及多個條件時),它使得它更不可讀,恕我直言。 – MBZ 2013-04-28 16:36:46

+0

很明顯,當轉換使得它對我更具可讀性時 - 但是決定它是否使其對其他人更具可讀性有點困難......您必須對目標受衆有一個好的概念。在這方面,選擇是*非常*主觀的IHMO - 但仍然必須作出選擇! – 2013-04-28 16:41:50

回答

9

這會提高性能嗎?

通常它不會影響性能。有可能工程師使用LINQ或者改善會降低性能,但在一般情況下不會降低性能。

這是否使代碼更具可讀性?

很多時候,是的,因爲它取代,強調力學與一個強調迭代的目的迭代的的構造。對力學

強調:

var jacks = new List<Person>(); 
foreach (var person in persons) 
{ 
    if (person.Name == "Jack") 
    { 
     jacks.Add(person); 
    } 
} 

「每到這個代碼遍歷的人,並找到一個名叫Jack的人添加它們 到列表命名千斤頂」。

重視宗旨:

var jacks = persons.Where(p => p.Name == "Jack").ToList(); 

「以他的名字是傑克的所有人員,並把它們放入一個列表,我們會打電話給該列表插孔。「

它也不會傷害第二個版本要短得多,所以你的大腦可以同時更容易消耗這一切比第一

又如:

var furryAnimals = furryThings.Intersect(animals).ToArray(); 

絕對沒有辦法能夠在沒有LINQ或編寫自己的等價物的情況下與這種清晰度相匹配。在這裏立即明確指出furryAnimals包含furryThingsanimals中的任何內容,這就是你所關心的。

不要關心這些集合的交集是如何計算的。計算可能涉及字典作爲實現細節。但是,從創建字典開始的替代版本的代碼會立即引起您關注最不重要的一件事:實現細節。

一般來說,我應該在什麼時候遵循ReSharper的建議,在這個問題上, ,當我不應該?

總是有例外的規則,所以我不會在這裏介紹一個。但總體而言,我們希望代碼正確,可維護且快速(通常按此順序)。我會假設代碼是正確的,所以無論何時你必須做出決定,都要考慮:

  • 這樣做的改變是否使代碼更清晰明白?它是否會使代碼在未來更易於修改?

如果你有具體證明的代碼的速度是關鍵,還要考慮:

  • 哪個版本運行得更快?
+0

這是錯誤的:「通常它不會影響性能」。在大多數情況下,LINQ會略微降低性能並增加內存流量(壞事)。這是可讀性的代價。 – 2013-04-29 08:19:18

+1

@DmitryOsinovskiy:我不太確定。你可以擴大一點嗎? – Jon 2013-04-29 08:39:18

+2

LINQ使用lambda(匿名代表)。委託調用有點慢,委託創建速度更慢,並且後續委託必須被垃圾收集。當然,除非在循環中使用LINQ一千次,否則這並不重要。 – 2013-04-29 11:45:07

1

Resharper不考慮代碼的可讀性,轉換爲LINQ。因此,它可以生成相當複雜的表達式,這些表達式比較難以理解經典循環。

轉換爲LINQ代碼本身不會改變性能,所以它更多的是代碼風格的偏好。

0

LINQ使代碼更具可讀性,但在大多數情況下,可讀性伴隨着性能成本。原因是lamdbas(匿名委託)是必須在內存中分配的類,並且之後會收集垃圾。那麼,CLR試圖在可能的時候聰明地緩存代表,但不幸的是這還不夠。此外,lamdba調用比簡單的方法調用稍慢。

這就是爲什麼ReSharper可以做到這一點:將代碼轉換爲LINQ並將LINQ轉換爲代碼。當你關心可讀性時,把所有東西都轉換成LINQ。當您關心性能時,請將轉換爲LINQ的檢測優先級設置爲低,並在您看到它時將LINQ轉換爲代碼。通常我首先將代碼編寫爲LINQ,然後使用ReSharper將其轉換爲代碼。真的節省了時間。