访问修改后的闭包:ReSharper
Posted
技术标签:
【中文标题】访问修改后的闭包:ReSharper【英文标题】:Access to modified closure: ReSharper 【发布时间】:2015-11-08 12:23:51 【问题描述】:我创建了一个处理数据库访问的库。我最近添加了事务处理;但是,我遇到了一个小问题。为了概述这一点,我编写了这个示例用于演示目的:
class Program
static void Main(string[] args)
String data = null;
DoAction(ref data, () =>
Console.WriteLine(data);
);
Console.ReadLine();
private static void DoAction(ref String data, Action action)
if (data == null)
data = "Initialized Data";
action();
我在“数据”变量的以下代码行中得到“访问修改后的闭包”下划线:
Console.WriteLine(data);
我了解修改 ref 数据变量可能会导致问题(例如,在运行 foreach 循环时)。但是,在以下情况下,我认为不会发生这种情况。
这是另一个版本,其中有一个循环进一步更改变量 - 输出符合预期:
class Program
static void Main(string[] args)
String data = null;
for (var i = 0; i < 10; i++)
DoAction(ref data, () =>
Console.WriteLine(data);
);
Console.ReadLine();
private static void DoAction(ref String data, Action action)
if (data == null)
data = "Initialized Data";
else
data += "|";
action();
ReSharper 让我可以创建一个局部变量,但我明确希望使用从 DoAction() 方法创建的字符串。如果我接受 ReSharpers 方法,它实际上会破坏代码。有没有其他方法可以解决这个问题?我想使用这种 Action 方法,但我也不希望 ReSharper 抱怨它(并且可能不会禁用 ReSharpers 检查)。
有什么建议吗?
【问题讨论】:
我还查看了:Access to Modified Closure (2),其中包含指向原始帖子评论中 ReSharper 文档的链接。 【参考方案1】:我建议首先避免为此使用ref
参数——这对我来说似乎是不必要的复杂。我会将DoAction
重写为:
static string DoAction(string data, Action<string> action)
data = data == null ? "Initialized Data" : data + "|";
action(data);
return data;
那么你可以:
data = DoAction(data, Console.WriteLine);
或者如果你想使用 lambda 表达式:
data = DoAction(data, txt => Console.WriteLine(txt));
如果您之后实际上不需要结果,您可以将 DoAction
设为 void
方法。 (不清楚为什么您需要返回结果和在DoAction
中执行的委托,但大概这在您更广泛的上下文中更有意义。)
【讨论】:
我明白 - 我也做过同样的事情。但是,对于 Console.WriteLine(string),我会有两次合适的变量。数据和txt。这可能会导致其他团队成员感到困惑。 @AlexanderFuchs:这是一个有点令人困惑的方法——为什么DoAction
负责计算一个新值并执行一个动作?如果不了解您真正想要实现的目标,很难说出最佳解决方案是什么,但使用ref
参数和对我来说似乎是个坏主意。
对不起,我没有理解 Lambda 之前的解决方案。这看起来不错!我会试试的
这个想法是让 sql 语句与事务一起执行。 DoAction 方法将创建一个事务并将其用于 Lambda 块中的所有查询。不知道这是否有意义。
@AlexanderFuchs:是的,这是有道理的,但是不清楚为什么需要将data
传递到方法中,而不是仅 在闭包中引用它。 【参考方案2】:
如果您确定该警告不合适,InstantHandleAttribute
记录为:
告诉代码分析引擎参数是否被完全处理 当调用的方法在堆栈上时。如果参数是委托, 表示在执行方法时执行委托。 如果参数是可枚举的,则表示它是可枚举的 方法执行时。
我想这正是你想要的。
您可以从 JetBrains.Annotations 包中获取属性,或者从 ReSharper 选项中复制粘贴。
【讨论】:
我会试试这个 亲爱的上帝,我为此搜索了很长时间,偶然发现了这个解决方案。我有同样的问题,有一个在方法中同步执行然后完成的操作,但 ReSharper 一直告诉我修改后的关闭警告。这是解决方案,无需解决方法。以上是关于访问修改后的闭包:ReSharper的主要内容,如果未能解决你的问题,请参考以下文章