私は次のコードを持っています:
string acctStatus = account.AccountStatus.ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
Account.AccountStatusはACCOUNTSTATUSタイプの列挙型であることに注意してください。 2行目で、ReSharperはacctStatusに対して「変更されたクロージャーへのアクセス」という警告を表示しています。推奨される操作Copy to local variableを実行すると、コードが次のように変更されます。
string acctStatus = realAccount.AccountStatus.ToString();
string s = acctStatus;
if (!SettableStatuses().Any(status => status == s))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
なぜこれが私が最初に持っていたものよりも優れているか、または好ましいのですか?
[〜#〜]編集[〜#〜]
また、ローカル変数をarrayでラップすることをお勧めします。これにより、次のようになります。
string[] acctStatus = {realAccount.AccountStatus.ToString()};
if (!SettableStatuses().Any(status => status == acctStatus[0]))
acctStatus[0] = ACCOUNTSTATUS.Pending.ToString();
これは実に奇妙に思えます。
警告の理由は、ループ内で変更中の変数にアクセスしている可能性があるためです。ただし、この「修正」は、この非ループコンテキストでは実際には何も行いません。
FORループがあり、ifがその中にあり、文字列宣言がその外側にあったとします。その場合、エラーは不安定なものへの参照を取得する問題を正しく識別します。
あなたが望まないものの例:
string acctStatus
foreach(...)
{
acctStatus = account.AccountStatus[...].ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
問題は、クロージャーがacctStatusへの参照を取得することですが、ループを繰り返すたびにその値が変更されます。 thatの場合、より良いでしょう:
foreach(...)
{
string acctStatus = account.AccountStatus[...].ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
変数のコンテキストはループであるため、変数をローカルコンテキスト内に移動したため(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);
}
私はnodeTypeタイプをローカルでキャプチャし、nodeTypeとHistoryItem crumb.ItemGuidをキャプチャし、crumbs [i] .ItemGuidではないことに注意してください。これにより、クロージャに変更されるアイテムへの参照が含まれないようになります。
ローカルを使用する前は、イベントは、私が期待したキャプチャされた値ではなく、現在の値でトリガーされていました。