Подтвердить что ты не робот

Сокращение для вложенной проверки нуля С#

Насколько я знаю, нет более сильного более элегантного способа написать следующее....

string src;
if((ParentContent!= null)
    &&(ParentContent.Image("thumbnail") != null)
    &&(ParentContent.Image("thumbnail").Property("src") != null))
    src = ParentContent.Image("thumbnail").Property("src").Value

Считаете ли вы, что должна быть функция языка С#, чтобы сделать это короче?
И если да, то как это будет выглядеть?
например, что-то вроде расширения? Оператор

string src = ParentContent??.Image("thumbnail")??.Property("src")??.Value;

Извините за довольно надуманный пример и мое упрощенное решение.

Изменить... Много лет спустя
Теперь это запланированная языковая функция, называемая оператором Null ?. https://roslyn.codeplex.com/discussions/540883 (Спасибо @Brian)

4b9b3361

Ответ 1

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

R NotNull<T, R>(this T src, Func<T, R> f) 
    where T : class where R : class {
  return src != null ? f(src) : null;
}

Теперь вы можете переписать свой пример следующим образом:

src = ParentContent.NotNull(p => p.Image("thumbnail")).
        NotNull(i => i.Property("src")).NotNull(src => src.Value);

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

Обратите внимание, что это добавляет метод NotNull ко всем типам .NET, что может быть немного неудобно. Вы можете решить это, указав простой тип-оболочку WrapNull<T> where T : class, содержащий только значение типа T и метод преобразования любого ссылочного типа в WrapNull и предоставления NotNull в типе WrapNull. Тогда код будет выглядеть так:

src = WrapNull.Wrap(ParentContent).NotNull(p => p.Image("thumbnail")).
        NotNull(i => i.Property("src")).NotNull(src => src.Value);

(Таким образом, вы не будете загрязнять IntelliSense каждого типа новым методом расширения)

С меньшими усилиями вы также можете определить операторы запросов LINQ для этого. Это немного перебор, но это можно написать (я не буду включать определения здесь, поскольку они немного дольше, но это возможно, если кому-то интересно: -)).

src = from p in WrapNull.Wrap(ParentContent)
      from i in p.Image("thumbnail").
      from src in i.Property("src")
      select src.Value;

Ответ 2

Было предложено и, по-видимому, отклонено командой:

Немного больше синтаксического сахара С# для нулей

Предложенный синтаксис выглядел бы как a.?b.?c() - очень полезный и недвусмысленный.

Мне бы очень хотелось это посмотреть, но похоже, что это не произойдет. Может быть, если на это проголосуют люди!

Ответ 3

Мы рассмотрели его для С# 4, но не имели бюджета. Это приятная функция, которую многие люди просят, поэтому, возможно, мы перейдем к будущей гипотетической языковой версии. Нет promises.

Ответ 4

Исправьте меня, если я ошибаюсь, но это можно решить, используя С# 6.0 оператор с нулевым условием:

string src = ParentContent?.Image("thumbnail")?.Property("src")?.Value;

Если src уже используется до назначения значения, вы можете использовать его следующим образом:

string src = ....;

// ...

src = ParentContent?.Image("thumbnail")?.Property("src")?.Value ?? src;

// ...

Ответ 5

Он по-прежнему оставляет желать лучшего, но я бы написал его так:

var src = ParentContent == null ? null
    : ParentContent.Image("thumbnail") == null ? null
    : ParentContent.Image("thumbnail").Property("src") == null ? null
    : ParentContent.Image("thumbnail").Property("src").Value;