当前位置: 首页 > 编程语言 > C#

共享匿名代表捕获的私有字段

时间:2023-04-10 22:20:21 C#

匿名代表捕获的私有字段classA{publiceventEventHandlerAEvent;}B类{私人A_foo;私人诠释_bar;publicvoidAttachToAEvent(){_foo.AEvent+=delegate(){...UseBar(_bar);...}}}由于委托捕获变量this._bar,它是否隐含地持有B的一个实例?是否会通过事件处理程序引用B的实例,并通过A的实例捕获变量?如果_bar是AttachToAEvent方法的局部变量,会有什么不同吗?因为在我的例子中,A的实例比B的实例寿命更长并且小得多,所以我担心这样做会导致“内存泄漏”。通过查看编译器生成的代码最容易理解,例如:publicvoidAttachToAEvent(){_foo.AEvent+=newEventHandler(this.Handler);}[CompilerGenerated]privatevoidHandler(objectsender,EventArgse){this.UseBar(this._bar);可以清楚地看到,创建的委托是一个实例委托(针对对象的实例方法),因此必须持有对该对象实例的引用。由于委托捕获变量this._bar,它是否隐含地持有B的一个实例?事实上,匿名方法只捕获this(不是this._bar)。从生成的代码中可以看出,构造的委托确实会持有对B实例的引用。它必须;如果委托已实施,该字段何时可按需阅读?请记住,捕获变量,而不是值。因为在我的例子中,A的实例比B的实例寿命更长并且小得多,所以我担心这样做会导致“内存泄漏”。是的,你有充分的理由。只要A实例可访问,B事件订阅者仍然可以访问。如果您不想对弱事件感兴趣,则需要覆盖它以在不再需要处理程序时注销它。如果_bar是AttachToAEvent方法的局部变量,会有什么不同吗?是的,它会的,因为捕获的变量将变成本地的而不是本地的。但是假设UseBar是一个实例方法,你的“问题”(如果你想那样想的话)就更糟了。编译器现在需要生成一个“记住”本地和包含B对象实例的事件侦听器。这是通过创建一个闭包对象并将其(实际上是它的实例方法)作为委托的目标来实现的。publicvoidAttachToAEvent(int_bar){闭包closure=newClosure();closure._bar=_bar;closure._bInstance=this;_foo.AEvent+=newEventHandler(closure.Handler);}[CompilerGenerated]privatesealedclassClosure{publicint_bar;公共B_bInstance;publicvoidHandler(objectsender,EventArgse){_bInstance.UseBar(this._bar);}}Ani的回答是正确的。总结并添加一些细节:由于委托捕获变量this._bar,它是否隐含地持有B的实例?是的。“这个”被捕获。会不会通过事件处理器引用B的实例,通过A的实例捕获变量?是的。如果_bar是AttachToAEvent方法的局部变量,会有什么不同吗?是的。在这种情况下,关闭的对象将保持本地状态;本地将被视为封闭域。因为在我的例子中,A的实例比B的实例寿命更长并且小得多,所以我担心这样做会导致“内存泄漏”。你的担心是完全正确的。你的情况已经很糟糕了,但当你运行两个匿名函数时,情况实际上会更糟。同一个局部变量声明空间中的所有匿名函数现在共享一个公共闭包,这意味着所有封闭的外部变量(包括“this”)的生命周期被延长到所有这些变量的最长生命周期。有关详细信息,请参阅我关于该主题的文章http://blogs.msdn.com/b/ericlippert/archive/2007/06/06/fyi-c-and-vb-closures-are-per-scope。aspx我们希望在假设的未来C#版本中修复此问题;我们可以更好地拆分闭包,而不是创建一个大闭包。但是,这不会很快发生。此外,C#5的“async/await”特性也可能会加剧当地人比您预期的寿命更长的情况。我们没有人对此感到兴奋,但正如他们所说,完美是令人敬畏的敌人。我们对如何调整异步块的代码生成器以改善这种情况有一些想法,但没有任何承诺。如果向事件添加匿名方法并希望它跟随,则必须将事件设置为null或将委托存储在列表中,以便稍后可以从事件中“-=”它。但是,是的,您可以从附加到事件的委托中引用的对象中获得“内存泄漏”。以上就是C#学习教程:匿名代表捕获的私有字段分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处: