简体   繁体   English

在c#中取消订阅事件的正确方法是什么?

[英]What's a proper way to unsibscribe from events in c#?

I have a model class with an event which I subscribe from other classes. 我有一个模型类,其中包含我从其他类订阅的事件。 I want to subscribe and un-subscribe in each class correctly. 我想在每个类中正确订阅和取消订阅。

  • First I want to guarantee that in MyClass I unsibscribe only once even that code is in few methods. 首先,我想保证在MyClass中我只取消一次,即使代码只有少数方法。
  • Second there are other classes except MyClass witch use OnMyEvent so I don't want to unintentionally unsibscribe from the event in the class. 其次除了MyClass之外还有其他类使用OnMyEvent,所以我不想无意中取消订阅该类中的事件。

      MyClass(IModel model) { _model = model; _model.OnMyEvent +=EventHandle; } Close() { _model.OnMyEvent -=EventHandle; } Disconnect() { //I want to check if OnMyEvent has already unsibscribed //Moreover OnMyEvent is used in other classes and //I don't want to mess up with it here _model.OnMyEvent -=EventHandle; } 

If you only subscribe once, it doesn't matter how many times you unsubscribe - unsubscribing when you don't have a subscription is a no-op. 如果你只认购一次,这不要紧,你多少次取消-取消订阅,当你没有订阅是无操作。 Equally, the entire point of the event API is that you can't accidentally unsubscribe other subscriptions (either other types, or other instances of the same type). 同样,事件API的整个要点是您不能意外取消订阅其他订阅(其他类型或相同类型的其他实例)。

As such, the code as shown should be fine, although it might be worth moving the two calls to a single method that handles this. 因此,显示的代码应该没问题,尽管将两个调用移动到处理此问题的单个方法可能是值得的。 That might be overkill, though. 但这可能有点矫枉过正了。

Also, if your type is IDisposable , make sure it gets called in that code-path too (presumably by calling Close() ). 此外,如果您的类型是IDisposable ,请确保它也在该代码路径中被调用(可能通过调用Close() )。

You can safely unsubscribe the same handler from an event multiple times. 您可以安全地多次取消订阅事件中的相同处理程序。 Additional checking is not required and would be contraproductive. 不需要额外的检查,这将是反作用的。

If you want to guarantee you only unsubscribe once, you can use the GetInvocationList method: 如果您想保证只取消订阅一次,可以使用GetInvocationList方法:

if (_model.OnMyEvent != null && _model.GetInvocationList().Contains(EventHandle))
{
    _model.OnMyEvent -= EventHandle
}

But as mentioned by the others, you can unsubscribe multiple times. 但正如其他人所提到的,您可以多次取消订阅。 If this really isn't a problem, keep it that way. 如果这确实不是问题,请保持这种状态。 The solution I propose is just code-noise. 我提出的解决方案只是代码噪声。 Simply unsubscribing in one line is much neater, and easier to read when your class starts to grow. 简单地取消订阅一行更简洁,当您的课程开始成长时更容易阅读。

You can also control subscriptions and unsubsriptions with this declaration. 您还可以使用此声明控制订阅和取消订阅。 But you also have to iterate through dictionary and call manually subscribed delegates. 但您还必须遍历字典并调用手动订阅的委托。

    private Dictionary<string, EventHandler> TestEvents { get; }

    public event EventHandler TestEvent
    {
        add
        {
            string name = value.GetType().FullName;
            if (!TestEvents.ContainsKey(name))
            {
                TestEvents.Add(name, value);
            }
        }
        remove
        {
            string name = value.GetType().FullName;
            if (TestEvents.ContainsKey(name))
            {
                TestEvents.Remove(name);
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM