C# ReSharper 警告 - 访问修改后的闭包
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1688465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ReSharper Warning - Access to Modified Closure
提问by Matt Grande
I have the following code:
我有以下代码:
string acctStatus = account.AccountStatus.ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
Note that account.AccountStatus is an enum of type ACCOUNTSTATUS. On the second line, ReSharper is giving me the warning "Access to Modified Closure" for acctStatus. When I do the recommended operation, Copy to local variable, it modifies the code to the following:
请注意, account.AccountStatus 是 ACCOUNTSTATUS 类型的枚举。在第二行,ReSharper 为 acctStatus 发出警告“访问修改后的闭包”。当我执行推荐的操作Copy to local variable 时,它将代码修改为以下内容:
string acctStatus = realAccount.AccountStatus.ToString();
string s = acctStatus;
if (!SettableStatuses().Any(status => status == s))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
Why is this better or preferable to what I had originally?
为什么这比我原来的更好或更可取?
EDIT
编辑
It also recommends Wrap local variable in array, which produces:
它还建议将局部变量包装在 array 中,这会产生:
string[] acctStatus = {realAccount.AccountStatus.ToString()};
if (!SettableStatuses().Any(status => status == acctStatus[0]))
acctStatus[0] = ACCOUNTSTATUS.Pending.ToString();
This seems downright wacky to me.
这对我来说似乎非常古怪。
采纳答案by Godeke
The reason for the warning is that inside a loop you might be accessing a variable that is changing. However, the "fix" isn't really doing anything for you in this non-loop context.
警告的原因是在循环内您可能正在访问正在更改的变量。但是,在这种非循环上下文中,“修复”并没有真正为您做任何事情。
Imagine that you had a FOR loop and the if was inside it and the string declaration was outside it. In that case the error would be correctly identifying the problem of grabbing a reference to something unstable.
想象一下,你有一个 FOR 循环,if 在它里面,而字符串声明在它外面。在这种情况下,错误将正确识别获取对不稳定事物的引用的问题。
An example of what you don't want:
你不想要的一个例子:
string acctStatus
foreach(...)
{
acctStatus = account.AccountStatus[...].ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
The problem is that the closure will grab a reference to acctStatus, but each loop iteration will change that value. In thatcase it would be better:
问题是闭包将获取对 acctStatus 的引用,但每次循环迭代都会更改该值。在这种情况下,它会更好:
foreach(...)
{
string acctStatus = account.AccountStatus[...].ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
As the variable's context is the loop, a new instance will be created each time because we have moved the variable inside the local context (the for loop).
由于变量的上下文是循环,因此每次都会创建一个新实例,因为我们已将变量移到本地上下文(for 循环)中。
The recommendation sounds like a bug in Resharper's parsing of that code. However, in many cases this is a valid concern (such as the first example, where the reference is changing despite its capture in a closure).
该建议听起来像是 Resharper 解析该代码的错误。但是,在许多情况下,这是一个有效的问题(例如第一个示例,尽管在闭包中捕获了引用,但引用仍在更改)。
My rule of thumb is, when in doubt make a local.
我的经验法则是,当有疑问时,做一个本地人。
Here is a real world example I was bitten by:
这是我被咬的一个真实世界的例子:
menu.MenuItems.Clear();
HistoryItem[] crumbs = policyTree.Crumbs.GetCrumbs(nodeType);
for (int i = crumbs.Length - 1; i > -1; i--) //Run through items backwards.
{
HistoryItem crumb = crumbs[i];
NodeType type = nodeType; //Local to capture type.
MenuItem menuItem = new MenuItem(crumb.MenuText);
menuItem.Click += (s, e) => NavigateToRecord(crumb.ItemGuid, type);
menu.MenuItems.Add(menuItem);
}
Note that I capture the NodeType type local, note nodeType, and HistoryItem crumb.ItemGuid, not crumbs[i].ItemGuid. This ensures that my closure will not have references to items that will change.
请注意,我捕获了 NodeType 类型 local、注意 nodeType 和 HistoryItem crumb.ItemGuid,而不是 crumbs[i].ItemGuid。这确保我的闭包不会引用将更改的项目。
Prior to using the locals, the events would trigger with the current values, not the captured values I expected.
在使用 locals 之前,事件将使用当前值触发,而不是我期望的捕获值。