One Liner:对 Lambda 事件处理程序的弱引用

发布于 2024-09-10 06:24:38 字数 464 浏览 2 评论 0原文

除了多次使用它会违反DRY<这一事实之外,你能看出这句话的缺点吗? /a> 原则?这看起来很简单,但事实上我还没有看到其他人提出它,这让我想知道它是否有一个缺点。

这段代码创建一个方法的WeakReference,然后注册调用引用目标的事件处理程序。

SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)();

谢谢,

Can you see downsides to this one-liner other than the fact that multiple uses of it would violate the DRY principle? It seems straightforward but the fact that I haven't seen others propose it makes me wonder if there's a downside to it.

This bit of code creates a WeakReference to a method and then registers an event handler that invokes the reference's target.

SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)();

Thanks,
Ben

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七禾 2024-09-17 06:24:38

我认为该模式没有达到您的预期。您是否试图阻止事件持有对当前对象的引用以防止内存泄漏? lambda 表达式将捕获 this 的值,以便计算 ProcessEvent(假设 ProcessEvent 是一个实例方法),因此您仍将拥有泄露。此代码与执行 SomeEvent += (sender, e) => 相同ProcessEvent();

您可能会尝试做类似这样的事情(这也不是您想要的):

var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();

现在 lambda 表达式将捕获 WeakReference,因此您不会对 this 有强引用。不幸的是,没有其他东西引用从 ProcessEvent 创建的委托,因此即使 this 仍然存在,它也会在下一次 GC 时被删除。 (这也不检查 Target 是否为空)。

您可以尝试这样的操作:

public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
    var reference = new WeakReference(action.Target);
    var method = action.Method;
    EventHandler handler = null;
    handler = delegate(object sender, EventArgs e)
    {
        var target = reference.Target;
        if (target != null)
        {
            method.Invoke(target, null);
        }
        else
        {
            remove(handler);
        }
    };
    return handler;
}

然后像这样使用它:

SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);

这将保留对 ProcessEvent 接收器的弱引用,并在收集事件后自动从事件中删除事件处理程序,这应该可以防止内存泄漏该事件定期引发。

I don't think that pattern does what you expect. Are you trying to prevent the event from holding a reference to the current object so as to prevent memory leaks? The lambda expression will capture the value of this in order to evaluate ProcessEvent (assuming ProcessEvent is an instance method), so you will still have the leak. This code is the same as doing SomeEvent += (sender, e) => ProcessEvent();.

You may be trying to do something more like this (which also isn't what you want):

var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();

Now the lambda expression will capture the WeakReference, so you won't have a strong reference to this. Unfortunately, nothing else is referencing the delegate created from ProcessEvent, so it will be removed on the next GC even if this is still alive. (This also doesn't check for Target being null).

You could try something like this:

public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
    var reference = new WeakReference(action.Target);
    var method = action.Method;
    EventHandler handler = null;
    handler = delegate(object sender, EventArgs e)
    {
        var target = reference.Target;
        if (target != null)
        {
            method.Invoke(target, null);
        }
        else
        {
            remove(handler);
        }
    };
    return handler;
}

and then use it like this:

SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);

That will keep a weak reference to the receiver of ProcessEvent, and will automatically remove the event handler from the event after it has been collected, which should prevent memory leaks as long as the event is raised regularly.

撑一把青伞 2024-09-17 06:24:38

它的可读性不太好。如果您必须通过单步调试来调试它,那么这些操作中的任何一个都可能失败,但那一行将会失败。此外,您只能得到堆栈跟踪中引用的单行。

为了可维护性,您通常希望避免在一行中做太多事情。

Its not very readable. And if you have to debug it by stepping through, any one of those actions could fail, but that single line would fail. Also, you'd only get that single line referenced in a stack trace.

You generally want to avoid doing too many things in a single line for maintainability.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文