C #: Инициализация обработчика событий с пустышкой - PullRequest
5 голосов
/ 15 июля 2009

Я видел такой код в некоторых местах:

public event SomeEventHandler SomeEvent = (s, e) => { };

Это рекомендуемый способ ведения дел? Что это решает, и есть ли какие-нибудь заметные побочные эффекты? Я все еще должен буду сделать нулевые проверки? Или это именно то, что мне больше не нужно делать? Будет ли сборка мусора работать как надо?


Например:

private PropertyChangedEventHandler propertyChanged;
private readonly object propertyChangedLock = new object();
public event PropertyChangedEventHandler PropertyChanged
{
    add
    {
        lock (propertyChangedLock)
            propertyChanged += value;
    }
    remove
    {
        lock (propertyChanged)
            propertyChanged -= value;
    }
}
protected void OnPropertyChanged(string propertyName)
{
    PropertyChangedEventHandler handler;
    lock (propertyChangedLock)
        handler = propertyChanged;

    if (handler != null)
        handler(this, new PropertyChangedEventArgs(propertyName));
}

Могу ли я изменить первую строку на это:

private PropertyChangedEventHandler propertyChanged = (s, e) => { };

А затем пропустить нулевую проверку в методе OnPropertyChanged? И если я тогда пропущу нулевую проверку, могу ли я тогда также пропустить блокировку? Если так, то это даст мне следующее:

protected void OnPropertyChanged(string propertyName)
{
    propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

Будет ли это безопасно при учете инициализации? Или есть какие-то побочные эффекты, которые я пропустил?

Ответы [ 2 ]

8 голосов
/ 15 июля 2009

Несмотря на то, что вам не нужно выполнять проверки на недействительность, если вы действительно хотите попытаться сделать событие поточно-безопасным, вам все равно нужно извлечь его в замке:

protected void OnPropertyChanged(string propertyName)
{
    PropertyChangedEventHandler handler;
    lock (propertyChangedLock)
    {
        handler = propertyChanged;
    }
    handler(this, new PropertyChangedEventArgs(propertyName));
}

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

Лично я рекомендую не пытаться сделать события потокобезопасными.

0 голосов
/ 15 июля 2009

Вы можете увидеть его как реализацию шаблона NULL Object .

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

Блокировки в вашей логике добавления / удаления должны остаться, если они необходимы сейчас. Они не имеют к этому никакого отношения. Они используются, чтобы избежать гоночных условий (но я не знаю, необходимы ли они в вашей ситуации)

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