Проверяющие делегаты к пустому указателю

Функция dateFromString возвращает NSDate, а не NSString. Вы должны изменить,

NSDate * theDate = [dateFormatter dateFromString: datetemp];

11
задан Joan Venge 9 June 2009 в 23:01
поделиться

5 ответов

Оригинальный (несколько неточный) Ответ:

По этому поводу много раз обсуждали.

Короче говоря: вы не можете гарантировать, что обработчик будет действительным даже при выполнении этой копии / check for null / execute step.

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

Вы также можете просто сделать:

if (OnTemperatureChange != null )
{
    OnTemperatureChange ( value );
}

И обработать исключение нулевой ссылки.

Иногда я добавляю обработчик по умолчанию, который ничего не делает, просто чтобы предотвратить исключение нулевой ссылки, но это серьезно влияет на производительность, особенно в случае, если другой обработчик не зарегистрирован.

Обновление 2014-07-10:

Я полагаюсь на Эрика Липперта .

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

12
ответ дан 3 December 2019 в 02:11
поделиться

Существует причина того, что указанный вами код рекомендуется вместо версии C. Ross. Однако Джон также прав в том, что есть еще одна проблема, если событие тем временем не зарегистрировано. Блог, на который я указал, рекомендует обработчику гарантировать, что они могут быть вызваны даже после отмены регистрации.

5
ответ дан 3 December 2019 в 02:11
поделиться

Во-первых, вы на самом деле не публикуете событие - так что в настоящий момент ваш код «подвержен риску» того, что люди полностью его испортят. Это должно быть:

public event TemperatureChangeHandler CurrentTemperatureChanged;

Имя «CurrentTemperatureChanged» важно для привязки данных (существует соглашение, которое использует среда выполнения - учитывая свойство Foo, она будет искать FooChanged). Однако , ИМО, это должен быть обычный обработчик событий . Привязка данных будет искать EventHandler , но что более важно: вы фактически не даете никакой информации в том случае, если подписчик не может получить ее, просто взглянув на obj.CurrentTemperature .

Я дам остальную часть ответа в терминах TemperatureChangeHandler , но я бы посоветовал вам (снова) переключиться на EventHandler :

public event EventHandler CurrentTemperatureChanged;

Подход:

TemperatureChangeHandler handler = CurrentTemperatureChanged;
if(handler != null) handler(value);

разумен, но (согласно другим ответам) существует небольшой риск того, что абоненты, которые думают, что они отключились, получают событие. Маловероятно в действительности.

Другой подход - метод расширения:

public static class TemperatureChangeExt {
    public static void SafeInvoke(this TemperatureChangeHandler handler,
             float newTemperature) {
        if (handler != null) handler(newTemperature);
    }
}

Затем в своем классе вы можете просто использовать:

        if (currentTemperature != value) {
            currentTemperature = value;
            CurrentTemperatureChanged.SafeInvoke(value);
        }
4
ответ дан 3 December 2019 в 02:11
поделиться

Я просто вижу небольшой рефакторинг, который можно было бы провести, но в остальном все выглядит неплохо ...

class Thermostat
{
    public delegate void TemperatureChangeHandler ( float newTemperature );

    public TemperatureChangeHandler OnTemperatureChange { get; set; }

    float currentTemperature;

    public float CurrentTemperature
    {
        get { return this.currentTemperature; }
        set
        {
                if (currentTemperature != value)
                {
                        currentTemperature = value;

                        if (this.OnTemperatureChange != null )
                        {
                                this.OnTemperatureChange.Invoke( value );
                        }
                }
        }
    }
}
1
ответ дан 3 December 2019 в 02:11
поделиться

Если класс Thermostat не должен быть потокобезопасным, тогда да, приведенный выше код в порядке - пока есть только один поток, обращающийся к этому экземпляру Thermostat, для OnTemperaChange нет возможности стать незарегистрированным между тестом на null и вызовом события.

Если вам нужно сделать термостат потокобезопасным, то вы можете прочитать следующую статью (в новинку для меня, похоже, хорошо прочитано):

http://www.yoda.arachsys.com/csharp/events.html

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

3
ответ дан 3 December 2019 в 02:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: