Проверьте, существуют ли родительские объекты
Я использую много данных базы данных в моем проекте, который экспортируется в разные классы. Например, у меня есть
transaction.Layout.Multimedia.Images.first();
Проблема в том, что эти свойства не обязательно доступны.
Таким образом, возможно, что transaction.Layout
Нуль, возможно, что transaction.Layout.Multimedia
является нулевым, и так далее.
В настоящее время я использую это для каждого свойства:
if (transaction.Layout != null)
{
if (transaction.Layout.Multimedia != null)
{
if (transaction.Layout.Multimedia.Images != null)
{
if (transaction.Layout.Multimedia.Images.count > 0)
{
var img = transaction.Layout.Multimedia.Images.first();
}
}
}
}
Мне было интересно, есть ли лучший способ, которым я могу проверить все родительские классы, чтобы убедиться, что нужное мне свойство доступно. Это не единственные объекты, которые я использую, есть и другие с совершенно другими именами.
заранее спасибо
3 ответа
Нет, пока нет. В новой версии.NET ( Roslyn) есть распространяющий оператор Null.
Тогда вы могли бы сделать:
if (transaction?.Layout?.Multimedia?.Image?.count > 0)
{
var img = transaction.Layout.Multimedia.Images.first();
}
На данный момент мы застряли с этим. Вы можете минимизировать количество необходимых строк, объединяя проверки, например так:
if ( transaction.Layout != null
&& transaction.Layout.Multimedia != null
&& transaction.Layout.Multimedia.Images != null
&& transaction.Layout.Multimedia.Images.count > 0
)
{
var img = transaction.Layout.Multimedia.Images.first();
}
Больше нечего делать.
Вы можете попробовать использовать Возможно монаду. Более подробное описание приведено в Цепных нулевых проверках и Монаде Возможно
With
а также If
методы расширения позволят вам написать:
var img = transaction.With(x => x.Layout)
.With(x => x.Multimedia)
.With(x => x.Images)
.If(x => x.count > 0))
.With(x => x.first());
With
Метод выглядит так:
public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
where TResult : class where TInput : class
{
if (o == null) return null;
return evaluator(o);
}
If
метод:
public static TInput If<TInput>(this TInput o, Func<TInput, bool> evaluator)
where TInput : class
{
if (o == null) return null;
return evaluator(o) ? o : null;
}
Это немного OT, но теоретически вы можете использовать методы расширения для достижения более простого синтаксиса:
public static class GetterExtensions {
public static LayoutClass GetLayout(this TransactionClass transaction) {
if (transaction == null)
return null;
else
return transaction.Layout;
}
public static MultimediaClass GetMultimedia(this LayoutClass layout) {
if (layout == null)
return null;
else
return layout.Multimedia;
}
public static ImagesClass GetImages(this MultimediaClass multimedia) {
if (multimedia == null)
return null;
else
return multimedia.Images;
}
public static int? GetCount(this ImagesClass images) {
if (images == null)
return null;
else
return images.count;
}
}
(Куда LayoutClass
, MultimediaClass
и т. д. являются типами соответствующих свойств).
Имея это, вы могли бы написать
if (transaction.GetLayout().GetMultimedia().GetImages().GetCount() > 0)
// ...
Это решение использует тот факт, что методы расширения могут быть вызваны на null
объекты без исключения. Они просто получают null
как их this
Параметр в этом случае. Также не int?
тип возврата (Nullable<int>
) из GetCount()
метод, который позволяет вернуть null
для целочисленного свойства.
Но если у вас много объектов (со многими свойствами), это решение, вероятно, нецелесообразно и требует много дополнительных усилий по обслуживанию. Кроме того, написание GetLayout()
вместо просто Layout
все еще менее элегантно.