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

Возможный дубликат:
Глубокая проверка нулей, есть ли лучший способ?

например, если вы выполняете логику в Foo1.Bar1.Foo2.Bar2 (и каждое из свойств может быть нулевым), вы не можете просто сделать это с foo.Bar1.Foo2.Bar2, потому что это возможно что вы получите нулевое ссылочное исключение

В настоящее время это то, что я делаю

if (foo1!=null && foo1.Bar1!=null && foo1.Bar1.Foo2 !=null && foo1.Bar1.Foo2.Bar2!=null)
return DoStuff(foo1.Bar1.Foo2.Bar2); //actually a logic based on the value of Bar2
else return null; 

Есть ли более элегантный или удобный способ, чтобы сделать это?

Ответ 1

Нет, нет.

Единственное, что может помочь, - это оценить, действительно ли DoStuff в правильном классе.

Ответ 2

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

public static bool AnyNull<TSource, TResult>(this TSource source, Func<TSource, TResult> selector)
        {
            try
            {
                selector(source);
                return false; ;
            }
            catch { return true; }
        }

используйте его:

if(!foo1.AnyNull(p=>p.Bar1.Foo2.Bar2))
    DoStuff(foo1.Bar1.Foo2.Bar2)

Ответ 3

Нет, к сожалению, нет. Я тоже часто хотел упрощенного синтаксиса!

Однако здесь довольно приличная альтернатива, с которой я столкнулся: создайте вспомогательный метод Null-Safe-Chain. Вот как это выглядит:

var bar2 = NullSafe.Chain(foo1, f1=>f1.Bar1, b1=>b1.Foo2, f2=>f2.Bar2);

Здесь метод:

public static TResult Chain<TA,TB,TC,TResult>(TA a, Func<TA,TB> b, Func<TB,TC> c, Func<TC,TResult> r) 
where TA:class where TB:class where TC:class {
    if (a == null) return default(TResult);
    var B = b(a);
    if (B == null) return default(TResult);
    var C = c(B);
    if (C == null) return default(TResult);
    return r(C);
}

Я также создал кучу перегрузок (с 2-6 параметрами). Это действительно хорошо для меня!