Как правильно отписаться от событий в C #? - PullRequest
4 голосов
/ 22 июня 2011

У меня есть класс модели с событием, на которое я подписываюсь из других классов.Я хочу подписаться и отписаться в каждом классе правильно.

  • Во-первых, я хочу гарантировать, что в MyClass я отписываюсь только один раз, даже если этот код есть в нескольких методах.
  • Во-вторых, существуют другие классы, кроме 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;
    }
    

Ответы [ 4 ]

11 голосов
/ 22 июня 2011

Если вы только подписываетесь один раз, не имеет значения как много раз вы отписываетесь - отмена подписки, когда у вас нет подписки, запрещена. Точно так же, весь смысл API событий в том, что вы не можете случайно отписаться от других подписок (других типов или других экземпляров того же типа).

Таким образом, показанный код должен быть в порядке, хотя, возможно, стоит перенести два вызова в один метод, который обрабатывает это. Хотя это может быть излишним.

Кроме того, если ваш тип IDisposable, убедитесь, что он также вызывается в этом пути кода (предположительно, путем вызова Close()).

2 голосов
/ 22 июня 2011

Вы можете безопасно отменить подписку одного и того же обработчика на событие несколько раз. Дополнительная проверка не требуется и будет контрпродуктивной.

1 голос
/ 22 июня 2011

Вы также можете контролировать подписки и неподписки с помощью этой декларации.Но вы также должны перебирать словарь и вызывать делегатов, подписанных вручную.

    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);
            }
        }
    }
1 голос
/ 22 июня 2011

Если вы хотите гарантировать отмену подписки только один раз, вы можете использовать метод GetInvocationList:

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

Но, как уже упоминали другие, вы можете отписаться несколько раз. Если это действительно не проблема, держите это так. Решение, которое я предлагаю, это просто кодовый шум. Просто отписаться в одной строке намного удобнее и легче читать, когда ваш класс начинает расти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...