2011-01-22 11 views
2
string reference; 
do { 
    reference = GenerateNewReference(); 
} while (currentItems.Exists(i=>i.Reference.Equals(reference)); 

ReSharperはこれについて、私にはAccess to Modified Closureと警告しています。私はそれを読んで理解するために最善を尽くしましたが、私のコードはまだ私にとってうまく感じられます。Do .. With Exists述部。変更されたクロージャへのアクセス?

私のコードに問題はありますか?

答えて

2

いいえ、List<T>.Existsメソッドが熱心に実行されるため、問題はありません。したがって、キャプチャされた変数の値の変化はすぐに「応答」されます。 doには変更されたクロージャがありますが、必ずしも(この場合のように)間違っているとは限りません。

一方、 "lambda"(本当にデリゲート)をループ内のリストに追加してからこれらのクエリを実行すると、Resharperの実際の変更されたクロージャの問題あなたについて警告しています。

警告を取り除きたい場合は、あなたができる:

string reference; 
do { 
    reference = GenerateNewReference(); 
    var refCopy = reference; 
} while (currentItems.Exists(i => i.Reference.Equals(refCopy)); 

ちょっとオフトピック:あなたはすべての修正閉鎖警告なし(検索を書く方法の空想をしたい場合)、次のようなユーティリティメソッドを書くことができます:

public static IEnumerable<T> Generate(Func<T> func) 
{ 
    if(func == null) 
     throw new ArgumentNullException("func"); 

    while(true) 
     yield return func(); 
} 

そしてとしてそれを使用します。

var result = MyExtensions.Generate(GenerateNewReference) 
         .First(reference => !currentItems.Exists(i => i.Reference.Equals(reference))); 
4

referenceの値はあなたのラムダの寿命にわたって変化しないので、あなたのケースでは問題ありません。しかし、resharperはそれを知らない。 resharperが見る限り、ラムダはより長い時間生き延びる可能性があり、その間にreferenceは値を変更します。

ルールは、あなたがこのようなコードを書くときに警告を表示することを意図している:IsOneラムダは参照することにより、および値ではなくmyIntに結合するので

int myInt=1; 
Func<int,bool> IsOne = i=>i==myInt; 
myInt=2; 
IsOne(1);//=> false 
IsOne(2);//=> true 

関連する問題