2010-04-07 32 views
1

我有最新的ReSharper的5.0版本(1655),在那裏我遇到的建議「以修改封訪問」在下面的代碼:訪問修改的閉包,這是一個ReSharper錯誤?

var now = new DateTime(1970, 1, 1); 
var dates = new List<DateTime>(); 
dates.Where(d => d > now); 
... 
now = new DateTime(); 

now lambda表達式內部強調與警告。

我很確定這是一個ReSharper錯誤,但它是真的嗎?

編輯:我應該更好地檢查,在代碼後面有一個now的任務。

EDIT 2喬恩斯基特下面幾乎回答了這個,但對於下面的answer

var query = dates.Where(d => d > now).ToList(); 

不應該通過這種立即執行查詢解決問題嗎?

+2

字面上只是在該代碼?在這些行之後沒有分配到「現在」? – 2010-04-07 10:44:25

+0

@Jon Skeet你是對的,有一個任務幾行下來!我會修改這個問題。 – 2010-04-07 10:48:00

回答

4

對,現在你已經修改了這個問題,這是完全合理的。您正在修改一個閉包內使用的變量 - 可以產生意想不到的結果:

var now = new DateTime(1970, 1, 1); 
var dates = new List<DateTime>(); 
var query = dates.Where(d => d > now); 
... 
now = new DateTime(1990, 1, 1); 
foreach (DateTime date in query) 
{ 
    // This will only see dates after 1990, not after 1970 
    // This would confuse many developers. 
} 

事實上,它不只是一個查詢開始時的事 - 你可以修改它同時遍歷結果

var now = new DateTime(1970, 1, 1); 
var dates = new List<DateTime>(); 
var query = dates.Where(d => d > now); 
... 
foreach (DateTime date in query) 
{ 
    now = date; 
    Console.WriteLine(date); 
} 

這將給日期嚴格遞增的序列...再次,有點混亂。

R#絕對正確地警告這個,國際海事組織。它可以有時是有用的 - 但應該非常小心使用。

+0

如果我調用'ToList()',應該不會立即執行查詢,從而防止這種情況? – 2010-04-07 10:55:33

+0

@hmemcpy:是的,沒錯。 – 2010-04-07 11:05:16

+0

但是警告仍然存在,所以也許這可能是一個ReSharper錯誤... – 2010-04-07 11:09:48

0

不,這是resharper認爲你正在修改集合的內容,而循環它,最有可能的是dates。你可以放心地忽略這一點。

+0

由於'now'是一個捕獲的變量,因此在對查詢進行評估之前對其進行的任何更改都很可能會產生與預期不同的結果,這是R#試圖突出顯示的結果。 – 2010-04-07 10:52:01

+0

-1:他不能安全地忽略它 – ANeves 2010-04-07 11:14:58

+0

嗯顯然問題被改變爲代碼他使用循環的代碼 – 2010-04-07 11:29:58

1

ReSharper警告你的是now的值在lambda表達式中被捕獲,而不是lambda表達式執行時的值。

解決你的問題,你需要使用它之前的now的值賦給一個局部變量:

var now = new DateTime(1970, 1, 1); 
var dates = new List<DateTime>{new DateTime(2001, 12, 12)}; 
DateTime localNow = now; 
dates.Where(d => d > localNow); 

now = new DateTime(2003, 12, 12); 

如果你想了解更多,ReSharper的論壇上有一個post,其中包括幾個鏈接進一步解釋。

相關問題