C# Resharper:隐式捕获的闭包:这个
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12953907/
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: Implicitly captured closure: this
提问by Aaron Maslen
I am getting this warning ("Implicity captured closure: this") from Resharper: does this mean that somehow this code is capturing the entire enclosing object?
我从 Resharper 收到此警告(“隐式捕获的闭包:this”):这是否意味着此代码以某种方式捕获了整个封闭对象?
internal Timer Timeout = new Timer
{
Enabled = false,
AutoReset = false
};
public Task<Response> ResponseTask
{
get
{
var tcs = new TaskCompletionSource<Response>();
Timeout.Elapsed += (e, a) => tcs.SetException(new TimeoutException("Timeout at " + a.SignalTime));
if (_response != null) tcs.SetResult(_response);
else ResponseHandler += r => tcs.SetResult(_response);
return tcs.Task;
}
}
I'm not sure how or why it's doing so - the only variable it should be capturing is the TaskCompletionSource, which is intentional. Is this actually a problem and how would I go about solving it if it is?
我不确定它是如何或为什么这样做 - 它应该捕获的唯一变量是 TaskCompletionSource,这是有意的。这实际上是一个问题,如果是,我将如何解决它?
EDIT: The warning is on the first lambda (the Timeout event).
编辑:警告在第一个 lambda(超时事件)上。
采纳答案by Aaron Maslen
It seems that the problem isn't the line I think it is.
似乎问题不是我认为的那条线。
The problem is that I have two lambdas referencing fields in the parent object: The compiler generates a class with two methods and a reference to the parent class (this).
问题是我有两个 lambda 引用父对象中的字段:编译器生成一个具有两个方法的类和一个对父类 ( this)的引用。
I think this would be a problem because the reference to thiscould potentially stay around in the TaskCompletionSource object, preventing it from being GCed. At least that's what I've found on this issue suggests.
我认为这将是一个问题,因为对的引用this可能会保留在 TaskCompletionSource 对象中,从而阻止它被 GC。至少这是我在这个问题上发现的建议。
The generated class would look something like this (obviously names will be different and unpronounceable):
生成的类看起来像这样(显然名称将不同且无法发音):
class GeneratedClass {
Request _this;
TaskCompletionSource tcs;
public lambda1 (Object e, ElapsedEventArgs a) {
tcs.SetException(new TimeoutException("Timeout at " + a.SignalTime));
}
public lambda2 () {
tcs.SetResult(_this._response);
}
}
The reason the compiler does this is probably efficiency, I suppose, as the TaskCompletionSourceis used by both lambdas; but now as long as a reference to one of those lambdas is still referenced the reference to Requestobject is also maintained.
我想编译器这样做的原因可能是效率,因为TaskCompletionSource两个 lambda 都使用 ; 但是现在只要对这些 lambda 表达式之一的引用仍然被引用,对Request对象的引用也会被维护。
I'm still no closer to figuring out how to avoid this issue, though.
不过,我仍然无法弄清楚如何避免这个问题。
EDIT: I obviously didn't think through this when I was writing it. I solved the problem by changing the method like this:
编辑:我在写它的时候显然没有考虑过这个。我通过改变这样的方法解决了这个问题:
public Task<Response> TaskResponse
{
get
{
var tcs = new TaskCompletionSource<Response>();
Timeout.Elapsed += (e, a) => tcs.SetException(new TimeoutException("Timeout at " + a.SignalTime));
if (_response != null) tcs.SetResult(_response);
else ResponseHandler += tcs.SetResult; //The event passes an object of type Response (derp) which is then assigned to the _response field.
return tcs.Task;
}
}
回答by SLaks
It looks like _responseis a field in your class.
它看起来像是_response您班级中的一个字段。
Referencing _responsefrom the lambda will capture thisin the closure, and will read this._responsewhen the lambda executes.
_response从 lambda引用将this在闭包中捕获,并this._response在 lambda 执行时读取。
To prevent this, you can copy _responseto a local variable and use that instead. Note that that will cause it to use the currentvalue of _responserather than its eventual value.
为了防止这种情况,您可以复制_response到局部变量并使用它。请注意,这将导致它使用当前值_response而不是其最终值。

