测试父对象是否存在

时间:2014-08-18 11:17:12

标签: c# .net null-check

我在我的项目中使用了很多数据库数据,这些数据是在不同的类中导出的。例如,我有

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 个答案:

答案 0 :(得分:8)

不,还没有 。新版本的.NET(Roslyn)具有Null propagating operator

然后你可以这样做:

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();
}

没有其他事可做了。

答案 1 :(得分:2)

您可以尝试使用Maybe monad。更详细的描述见Chained null checks and the Maybe monad

WithIf扩展方法可让您编写:

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;
}

答案 2 :(得分:1)

这有点旧,但从理论上讲,您可以使用扩展方法来实现更简单的语法:

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;
  }
}

(其中LayoutClassMultimediaClass等是相应属性的类型。)

有了这个,你可以写

if (transaction.GetLayout().GetMultimedia().GetImages().GetCount() > 0)
  // ...

此解决方案利用了这样一个事实:可以在null个对象上调用扩展方法而不会抛出异常。在这种情况下,他们只需将null作为this参数。也不是int?方法的Nullable<int>返回类型(GetCount()),它允许为整数属性返回null

但是如果你有许多对象(具有许多属性),这个解决方案可能是不切实际的,需要大量额外的维护工作。另外,写GetLayout()而不仅仅是Layout仍然不那么优雅。