代码之家  ›  专栏  ›  技术社区  ›  Spence

C嵌套的空签入if语句

  •  1
  • Spence  · 技术社区  · 16 年前

    我有一个关于编程风格和C语言设计的问题,一般来说,我想知道是否有更好的方法来做我正在做的事情。

    如果您有一个复杂的数据对象,其属性可以为空,但您希望检查或操作数据(如果有),则不能这样写一行

    if(Myobject.MyNestedObject != null || Myobject.MyNestedObject.Property != null)
    {
       //code
    }
    

    因为编译器实际上会调用这两行代码来计算if语句。

    相反,你必须(我相信)写:

    if(Myobject.MyNestedObject != null)
    {
       if(Myobject.MyNestedObject.Property != null)
       {
          //code
       }
    }
    

    有没有比这更好的款式?我正在考虑如何使用空合并(??)但是如果您试图在同一语句中使用MyNestedObject的任何内容,它仍然会抛出。

    更多信息:

        L_01b4: ldarg.1 
        L_01b5: callvirt instance class [Myassembly]MyClass.MyObject [MyAssembly]MyClass::get_MyObject()
        L_01ba: brtrue.s L_01cc
        L_01bc: ldarg.1 
        L_01bd: callvirt instance class [MyAssembly]MyClass.MyObject [MyAssembly]MyClass::get_MyObject()
        L_01c2: callvirt instance class [MyAssembly]MyClass.MyNestedObject [MyAssembly]MyClass.MyNestedObject::get_MyNestedObject()
        L_01c7: ldnull 
        L_01c8: ceq 
        L_01ca: br.s L_01cd
        L_01cc: ldc.i4.0 
        L_01cd: stloc.2 
        L_01ce: ldloc.2 
        L_01cf: brtrue L_0285
        L_01d4: nop 
    

    据我所知,它的意思是在l ba,如果调用返回true,而不是null或非0(即,如果对象为空,则不会执行分支,然后控制流将线性继续)。这当然会执行l_01c2,因为myClass.myObject为空,所以会引发空引用异常。

    我错过什么了吗?这是.NET 3.5 C编译器。

    4 回复  |  直到 15 年前
        1
  •  19
  •   chakrit Dutchie432    16 年前

    结合@chris和@aj答案:

    我想你要的是接线员,而不是。

    if (Myobject.MyNestedObject != null &&
        Myobject.MyNestedObject.Property != null)
    {
        //code
    }
    

    而C的运算符使用短路计算,因此如果第一个表达式返回false,则不会计算第二个表达式。

        2
  •  4
  •   aJ.    16 年前
    if( Myobject.MyNestedObject != null && 
                 Myobject.MyNestedObject.Property != null)
    {
    //code
    }
    
        3
  •  2
  •   Chris    16 年前

    C使用懒惰的检查,所以您的第一个代码应该很好(当然,将更改为&&C!)

    更新-这里是: http://msdn.microsoft.com/en-gb/library/6373h346.aspx “ 手术

    X氏Y

    对应于操作

    X Y

    但如果x为真,则不计算y(因为无论y的值是什么,or操作的结果都是真的)。这就是所谓的“短路”评估。 “

    再次更新-应该使用&&!

        4
  •  1
  •   Jim Arnold    16 年前

    我要补充一点强制性的建议,即必须深入挖掘公共属性层通常意味着您暴露了太多的内部状态,并且您正在遍历的类应该为您完成这项工作。我还希望对象首先确保其属性不返回空值。

    当然也有边缘案例,但这些都是很好的经验法则。