Чем больше я пишу на C# 6, тем больше убеждаюсь в том, насколько оператор
Рассмотрим следующую задачку. Имеется поставщик, у поставщика есть контактное лицо, у контактного лица есть домашний адрес, у домашнего адреса есть первая строка, а эту самую первую строку мы и хотим найти. Раньше мне пришлось бы писать код с большим уровнем вложенности, проверяя на
Но теперь у нас есть C# 6, с ним код можно привести на намного более читаемому виду:
Оператор
Всем нам доводилось видеть классы, которые реализовывают интерфейс
Заметили неладное? Код упадёт в случае, если у события
Окей, стало чутка получше. Вполне возможно, что этот код в большинстве случаев будет работать. Впрочем, race condition никто не отменял: если подписчик отпишется от события в момент после того, как мы проверим
Ох, кода стало много, сложно всё это запомнит и каждый раз вызывать
Код получился короче, читается легче, все необходимые проверки выполняются, проблем нет.
А теперь такая ситуация: имеется объект некоторого типа, описание которого нам известно. Нужно понимать, что этот объект может реализовывать интерфейсы, о которых типу ничего не известно. Обычно это не такая уж и проблема, но что, если объект реализует
Оператор
Я нашёл два случая, когда оператор
Случай второй: я хочу вернуть значение
Добавление рассматриваемого оператора заставило меня осознать насколько часто встречаются проверки на
?. (null coalescing operator) помогает писать чистый простой и понятный код. Сегодня я покажу 4 ситуации, в которых он может быть очень полезен.Большая вложенность
Рассмотрим следующую задачку. Имеется поставщик, у поставщика есть контактное лицо, у контактного лица есть домашний адрес, у домашнего адреса есть первая строка, а эту самую первую строку мы и хотим найти. Раньше мне пришлось бы писать код с большим уровнем вложенности, проверяя на
null каждое значение в цепочке:var location = default(string);
if (vendor != null)
{
if (vendor.ContactPerson != null)
{
if (vendor.ContactPerson.HomeAddress != null)
{
location = vendor.ContactPerson.HomeAddress.LineOne;
}
}
}
Но теперь у нас есть C# 6, с ним код можно привести на намного более читаемому виду:
var location = vendor?.ContactPerson?.HomeAddress?.LineOne;
Оператор
?. сделает так, что как только в одном из свойств цепочки окажется null, дальнейшее вычисление выражения производится не будет. Посмотрим ещё несколько примеров. INotifyPropertyChanged и похожие API
Всем нам доводилось видеть классы, которые реализовывают интерфейс
INotifyPropertyChanged. В них можно встретить свойства следующего вида:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Заметили неладное? Код упадёт в случае, если у события
INotifyPropertyChanged.PropertyChanged нет подписчиков. В такой ситуации многие разработчики начинают писать так:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Окей, стало чутка получше. Вполне возможно, что этот код в большинстве случаев будет работать. Впрочем, race condition никто не отменял: если подписчик отпишется от события в момент после того, как мы проверим
PropertyChanged != null, но до того, как вызовется PropertyChanged, то программа всё-таки упадёт. И произойдёт это в самый неподходящий момент через несколько месяцев после установки приложения у клиента. Давайте исправим эту досадную проблему: сохраним ссылку на PropertyChnaged в локальную переменную handler проверим её на null, после чего будем работать с этой самой локальной переменной, а не с публичным событием PropertyChnaged:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Ох, кода стало много, сложно всё это запомнит и каждый раз вызывать
PropertyChanged грамотно. В большой программе кто-нибудь где-нибудь обязательно забудет сделать все проверки. Что же делать? C# 6 спасёт нас! Все наши проверки легко заменить с помощью оператора ?. и вызова метода Invoke:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Код получился короче, читается легче, все необходимые проверки выполняются, проблем нет.
Управление ресурсами
А теперь такая ситуация: имеется объект некоторого типа, описание которого нам известно. Нужно понимать, что этот объект может реализовывать интерфейсы, о которых типу ничего не известно. Обычно это не такая уж и проблема, но что, если объект реализует
IDisposable. Представьте себе злого гения, который решил отправить на пенсию одного из своих приспешников. Соответствующий код будет выглядеть следующим образом:public void RetireHenchman()
{
var disposableMinion = Minion as IDisposable;
if (disposableMinion != null)
disposableMinion.Dispose();
Minion = null;
}
Оператор
?. опять поможет улучшить качество нашего кода:public void RetireHenchman()
{
(Minion as IDisposable)?.Dispose();
Minion = null;
}
LINQ-запросы
Я нашёл два случая, когда оператор
?. может быть полезен в LINQ-запросах. Случай первый: я хочу создать запрос с использованием метода SingleOrDefault(), а у полученного объекта (если он существует) обратиться к некоторому свойству. Нет ничего проще:var created = members.SingleOrDefault(e => e.name == "dateCreated")?.content;
Случай второй: я хочу вернуть значение
null, если исходная последовательность равна null:members?.Select(m => (XElement)XmlValue.MakeValue(m))
Заключение
Добавление рассматриваемого оператора заставило меня осознать насколько часто встречаются проверки на
null и насколько короче и читаемее можно сделать код с использованием нового синтаксиса. Благодаря ?. я стал писать код иначе. Не могу дождаться, когда же в свет выйдет финальный релиз C# 6, чтобы я мог отдать моим заказчикам новую версию исходников.This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий