【问题标题】:Nullcheck multi level objectNullcheck 多级对象
【发布时间】:2017-04-11 20:25:48
【问题描述】:

在继续之前,我一直在尝试一些简单的方法来检查多个嵌套对象以查看是否有任何为空。如果可能的话,我正在尝试使用空条件运算符将多个嵌套的 if 语句替换为单个语句。

到目前为止,我有这样的事情:

if ((Object1?.Object2?.Object3?.Object4 != null) ? true : false)
{
...
}

以上内容是否可以有效地识别 Object1 2 3 或 4 是否为 null,如果是则返回 false?我很想知道是否有人有更好的解决方案?

TIA

【问题讨论】:

  • ' ? true : false' 不需要
  • 以这种方式使用语法是可以的,但是要求你在这么多关卡中这样做的设计是有问题的。

标签: c#


【解决方案1】:

您不需要返回 false 或 true - 布尔条件本身具有布尔值:

if (Object1?.Object2?.Object3?.Object4 != null)

如果其中任何一个为空,这部分是检查嵌套对象的完全有效选项。您可以在 null-conditional operator 文档中找到完全相同的示例:

// null if customers, the first customer, or Orders is null  
int? count = customers?[0]?.Orders?.Count();

及解释:

最后一个例子演示了空条件运算符是 短路。如果条件成员链中的一个操作 访问和索引操作返回 null,然后是链的其余部分 执行停止。

【讨论】:

  • 所以只有当所有对象都不为空时,这才会评估为真?如果说 Object2 为空,不会抛出异常?
  • @Nugs 是的,完全正确
  • @Nugs 正确的是 ?. 运算符的全部要点。它只计算找到的第一个空值,然后返回一个default(Object4Type)(如果Object4Type 是一个结构,则返回一个default(Nullable<Object4Type>))与!= null 进行比较。
  • 太棒了,我认为我在正确的轨道上,但想确认并更好地了解如何最好地使用 Null 条件运算符。我感谢快速的教训和确认家伙!谢谢
  • 并确保感谢 C# 团队的这一工作。空安全点运算符是 C# 6 语言规范中的一个相当新的补充,与 .NET 4.5 和 Visual Studio 2015 一起发布。在此之前,最好的解决方案是一个看起来像 Object1.OrDefault(o=>o.Object2.Object3.Object4) 的扩展方法,基本上是包装好的尝试评估 lambda 的 try-catch 块,捕获任何 NullReferenceExceptions 或 InvalidOperationExceptions 并在这些情况下返回 null。空安全点更干净。
【解决方案2】:

代码

public void Foo()
{
    if ((Object1?.Object2?.Object3?.Object4 != null) ? true : false)
    {
    ...
    }
}

逻辑上等价于

public void Foo()
{
    if ((NullCheck(Object1) != null) ? true : false)
    {
    ...
    }
}

private Object4Type NullCheck(Object1Type object1)
{
    if(!Object.RefrenceEquals(object1, null)) //This is "Object1?."
    {
        var tmpObject2 = tmpObject1.Object2;
        if(!Object.RefrenceEquals(tmpObject2, null)) //This is "Object2?."
        {
            var tmpObject3 = tmpObject2.Object3;
            if(!Object.RefrenceEquals(tmpObject3, null)) //This is "Object3?."
            {
                return tmpObject3.Object4;
            }        
        }
    }
    return default(Object4Type);
}

或者如果 Object4Type 是一个结构体

public void Foo()
{
    if ((NullCheck(Object1) != null) ? true : false)
    {
    ...
    }
}

private Nullable<Object4Type> NullCheck(Object1Type object1)
{
    if(!Object.RefrenceEquals(object1, null)) //This is "Object1?."
    {
        var tmpObject2 = tmpObject1.Object2;
        if(!Object.RefrenceEquals(tmpObject2, null)) //This is "Object2?."
        {
            var tmpObject3 = tmpObject2.Object3;
            if(!Object.RefrenceEquals(tmpObject3, null)) //This is "Object3?."
            {
                return tmpObject3.Object4;
            }        
        }
    }
    return default(Nullable<Object4Type>);
}

因此,您的... 将仅在所有对象都不为 null 并且较低级别的对象为 null 时运行,以后的对象永远不会被评估。

【讨论】:

    【解决方案3】:

    你所拥有的就是目前做你想做的最好的方式。我想回答是为了说明如果您无法访问最新的 C# 6 语言功能,什么是必要的。这是在 .NET 3.5-4.0 中进行相同检查的下一个对开发人员最友好的方式:

        //boilerplate, off in your extension method library
        public static TOut OrDefault<TIn, TOut>(this TIn input, 
            Func<TIn, TOut> possiblyNullFunc)
        {
            try { return possiblyNullFunc(input); }
            catch (NullReferenceException) //for most reference types
            { return default(TOut); }
            catch (InvalidOperationException) //for Nullable<T>
            { return default(TOut); }
        }
    
        ...
    
        //usage
        if (Object1.OrDefault(o=>o.Object2.Object3.Object4) != null)
        {
            ...
        }
    

    它运行良好,直到您尝试在自己的类中使用InvalidOperationException 来处理空成员访问以外的情况。

    仍然胜过这一点,尤其是如果您必须经常进行此检查:

    if(Object1 != null
        && Object1.Object2 != null
        && Object1.Object2.Object3 != null
        && Object1.Object2.Object3.Object4 != null)
    {
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      • 2016-10-08
      • 2010-10-08
      • 2019-05-07
      • 1970-01-01
      相关资源
      最近更新 更多