ReSharper警告 - 访问修改后的关闭

Mat*_*nde 37 c# resharper warnings

我有以下代码:

string acctStatus = account.AccountStatus.ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
    acctStatus = ACCOUNTSTATUS.Pending.ToString();
Run Code Online (Sandbox Code Playgroud)

请注意,account.AccountStatus是ACCOUNTSTATUS类型的枚举.在第二行,ReSharper向我发出了acctStatus的"访问修改后的关闭"的警告.当我执行建议的操作,复制到本地变量时,它将代码修改为以下内容:

string acctStatus = realAccount.AccountStatus.ToString();
string s = acctStatus;
if (!SettableStatuses().Any(status => status == s))
    acctStatus = ACCOUNTSTATUS.Pending.ToString();
Run Code Online (Sandbox Code Playgroud)

为什么这比我原来的更好或更好?

编辑

它还建议在数组中包装局部变量,它产生:

string[] acctStatus = {realAccount.AccountStatus.ToString()};
if (!SettableStatuses().Any(status => status == acctStatus[0]))
    acctStatus[0] = ACCOUNTSTATUS.Pending.ToString();
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎很奇怪.

God*_*eke 35

警告的原因是在循环内部您可能正在访问正在更改的变量.但是,在这种非循环上下文中,"修复"并没有真正为您做任何事情.

想象一下,你有一个FOR循环,if在里面,字符串声明在它之外.在这种情况下,错误将正确地识别抓取对不稳定的东西的引用的问题.

你不想要的一个例子:

string acctStatus

foreach(...)
{
  acctStatus = account.AccountStatus[...].ToString();
  if (!SettableStatuses().Any(status => status == acctStatus))
      acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
Run Code Online (Sandbox Code Playgroud)

问题是闭包会获取对acctStatus的引用,但每次循环迭代都会改变该值.在那种情况下会更好:

foreach(...)
{
  string acctStatus = account.AccountStatus[...].ToString();
  if (!SettableStatuses().Any(status => status == acctStatus))
      acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
Run Code Online (Sandbox Code Playgroud)

由于变量的上下文是循环,因此每次都会创建一个新实例,因为我们已将变量移动到本地上下文(for循环)中.

这个建议听起来像是Resharper解析该代码的一个错误.但是,在许多情况下,这是一个有效的问题(例如第一个例子,尽管它在闭包中捕获,但引用正在改变).

我的经验法则是,如果有疑问,那就是当地人.

这是一个我被咬过的真实世界的例子:

        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);
        }
Run Code Online (Sandbox Code Playgroud)

请注意,我捕获NodeType类型local,note nodeType和HistoryItem crumb.ItemGuid,而不是crumbs [i] .ItemGuid.这可以确保我的闭包不会引用将要更改的项.

在使用本地之前,事件将使用当前值触发,而不是我预期的捕获值.