Можно ли как-то сократить это утверждение?
if (obj != null)
obj.SomeMethod();
потому что я пишу это много, и это довольно раздражает. Единственное, что я могу придумать, - это реализовать шаблон Null Object , но это не то, что я могу делать каждый раз, и это, конечно, не решение для сокращения синтаксиса.
И аналогичная проблема с событиями, где
public event Func<string> MyEvent;
а затем вызвать
if (MyEvent != null)
MyEvent.Invoke();
Ответы:
Начиная с C # 6, вы можете просто использовать:
или:
Это
?.
оператор с нулевым распространением и вызовет.Invoke()
короткое замыкание, когда операндnull
. Доступ к операнду осуществляется только один раз, поэтому нет риска возникновения проблемы «изменение значения между проверкой и вызовом».===
До C # 6 нет: не существовало нулевого безопасного волшебства, за одним исключением; методы расширения - например:
теперь это действительно:
В случае событий это имеет то преимущество, что также удаляет условие гонки, то есть вам не нужна временная переменная. Обычно вам понадобятся:
но с:
мы можем просто использовать:
источник
?.
- в VB14 и вышеЧто вы ищете является Null Условный (не «сливаясь») Оператор:
?.
. Он доступен с C # 6.Ваш пример был бы
obj?.SomeMethod();
. Если obj имеет значение null, ничего не происходит. Когда метод имеет аргументы, например,obj?.SomeMethod(new Foo(), GetBar());
аргументы не оцениваются, еслиobj
имеет значение null, что имеет значение, если оценка аргументов будет иметь побочные эффекты.И возможна цепочка:
myObject?.Items?[0]?.DoSomething()
источник
Метод быстрого расширения:
пример:
или альтернативно:
пример:
источник
События могут быть инициализированы с помощью пустого делегата по умолчанию, который никогда не удаляется:
Нет необходимости в нулевой проверке.
[ Обновление , спасибо Бевану за указание на это]
Однако имейте в виду возможное влияние на производительность. Быстрый микротест, который я провел, показывает, что обработка события без подписчиков происходит в 2-3 раза медленнее при использовании шаблона «делегат по умолчанию». (На моем двухъядерном ноутбуке с частотой 2,5 ГГц это означает 279 мс: 785 мс для сбора 50 миллионов событий без подписки.) Это может быть проблемой для горячих точек приложений.
источник
Да, в C # 6.0 - https://msdn.microsoft.com/en-us/magazine/dn802602.aspx .
источник
В этой статье Яна Гриффитса представлены два разных решения проблемы, которые, по его мнению, представляют собой изящные уловки, которые вам не следует использовать.
источник
Предлагаемый метод расширения Cerating на самом деле не решает проблемы с условиями гонки, а скорее скрывает их.
Как указано, этот код является элегантным эквивалентом решения с временной переменной, но ...
Проблема с обоими заключается в том, что возможно, что подписчик события может быть вызван ПОСЛЕ того, как он отписался от события . Это возможно, потому что отмена подписки может произойти после того, как экземпляр делегата будет скопирован во временную переменную (или передан как параметр в методе выше), но до вызова делегата.
В целом поведение клиентского кода в таком случае непредсказуемо: состояние компонента уже не могло позволить обрабатывать уведомление о событии. Можно написать клиентский код так, чтобы он справлялся с этим, но это возложит на клиента ненужную ответственность.
Единственный известный способ обеспечить безопасность потока - использовать инструкцию блокировки для отправителя события. Это гарантирует, что все подписки \ отписки \ вызовы будут сериализованы.
Чтобы быть более точным, блокировку следует применить к тому же объекту синхронизации, который используется в методах доступа к событию add \ remove, который по умолчанию является this.
источник
Я согласен с ответом Кенни Элиассона. Используйте методы расширения. Вот краткий обзор методов расширения и необходимого вам метода IfNotNull.
Методы расширения (метод IfNotNull)
источник
Может быть, не лучше, но, на мой взгляд, более читабельным будет создание метода расширения
источник
return obj == null
значит. Что он вернетobj
естьnull
метод вернетсяtrue
, я думаю.null
? Я почти уверен, что это не работает с собственными методами типа, поэтому сомневаюсь, что это будет работать и с методами расширения. Я считаю , что лучший способ проверить , если объект находитсяnull
внеobj is null
. К сожалению, проверить , если объект не неnull
требует упаковки в скобках, что является неудачным.Для этого в C # есть малоизвестный нулевой оператор ??. Может быть полезно:
http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx
источник