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

ReSharper警告我有关此事的信息,称为Access to Modified Closure。我尽我所能来阅读和理解它,但我的代码对我来说似乎仍然很好。做..虽然..与存在的谓词。访问修改后的关闭?

我的代码有问题吗?

回答

2

不,没有问题,因为List<T>.Exists方法急切地执行。因此,捕获的变量的值的变化立即“回复”。你有一个修改闭包,但不一定(在这种情况下)是错误的。另一方面,如果您将“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的值在你的lambda的生命周期中不会改变。但resharper不知道这一点。至于resharper可以看到lambda可能会存活更长的时间,在此期间reference更改其值。

该规则的目的是提醒你,当你像这样写代码:

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

因为IsOne拉姆达通过引用结合myInt,而不是价值。