Jam*_*ing 5 c# linq resharper closures
这里看到几个类似的问题,但它们似乎都不是我的问题......
我理解(或者我认为我理解)闭包的概念,并理解什么会导致Resharper抱怨访问修改后的闭包,但在下面的代码中我不明白我是如何违反闭包的.
因为primaryApps在for循环的上下文中声明,所以primary在我处理时不会改变primaryApps.如果我primaryApps在for循环之外声明,那么绝对,我有封闭问题.但为什么在下面的代码?
var primaries = (from row in openRequestsDataSet.AppPrimaries
select row.User).Distinct();
foreach (string primary in primaries) {
// Complains because 'primary' is accessing a modified closure
var primaryApps = openRequestsDataSet.AppPrimaries.Select(x => x.User == primary);
Run Code Online (Sandbox Code Playgroud)
Resharper是不是很聪明,没有弄清楚这不是问题,还是有理由关闭是我在这里看不到的问题?
Jar*_*Par 10
问题出现在以下声明中
因为在for循环的上下文中声明了primaryApps,所以在我处理primaryApps时,primary不会改变.
Resharper根本无法100%验证这一点.引用闭包的lambda传递给this循环上下文之外的函数:AppPrimaries.Select方法.此函数本身可以存储生成的委托表达式,稍后执行它并直接捕获迭代变量问题.
正确地检测这是否可行是一项艰巨的任务,坦率地说不值得付出努力.相反,ReSharper采取安全路线并警告有关捕获迭代变量的潜在危险.
因为在for循环的上下文中声明了primaryApps,所以在我处理primaryApps时,primary不会改变.如果我在for循环之外声明了primaryApps,那么绝对,我有封闭问题.但为什么在下面的代码?
贾里德是对的; 为了证明为什么你的结论不遵循你的前提逻辑,让我们创建一个程序,在for循环的上下文中声明primaryApps,并且仍然受到捕获的循环变量问题的困扰.很容易做到这一点.
static class Extensions
{
public IEnumerable<int> Select(this IEnumerable<int> items, Func<int, bool> selector)
{
C.list.Add(selector);
return System.Enumerable.Select(items, selector);
}
}
class C
{
public static List<Func<int, bool>> list = new List<Func<int, bool>>();
public static void M()
{
int[] primaries = { 10, 20, 30};
int[] secondaries = { 11, 21, 30};
foreach (int primary in primaries)
{
var primaryApps = secondaries.Select(x => x == primary);
// do something with primaryApps
}
C.N();
}
public static void N()
{
Console.WriteLine(C.list[0](10)); // true or false?
}
}
Run Code Online (Sandbox Code Playgroud)
声明"primaryApps"的地方完全无关紧要.唯一相关的是闭包可能在循环中存活,因此有人可能会在以后调用它,错误地期望闭包中捕获的变量被值捕获.
Resharper无法知道Select的特定实现不会将选择器藏起来以便以后使用; 事实上,这正是他们所有人所做的.Resharper怎么会知道他们碰巧把它藏在一个以后无法进入的地方?
| 归档时间: |
|
| 查看次数: |
1366 次 |
| 最近记录: |