C#嵌套空检查if语句

时间:2009-04-20 04:27:52

标签: c# coding-style null language-features

我对编程风格和C#语言设计有一个疑问,我很想知道是否有更好的方法来做我正在做的事情。

如果你有一个复杂的数据对象,其属性可以为null,但你想检查或操作数据(如果有的话),你就不能写这样的行

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

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

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

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

有比这更好的风格吗?我正在尝试考虑如何使用null coalesce(??)但如果你尝试在同一个语句中使用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_01ba如果调用返回true,不是null或非0(即如果对象为null,则不采用分支,然后控制流线性地继续)。这当然会执行L_01c2,它将抛出一个空引用异常,因为Myclass.MyObject为null。

我错过了什么。这是.net 3.5 C#编译器。

4 个答案:

答案 0 :(得分:19)

结合@Chris和@aJ回答:

我想你想要&&运算符,而不是||。

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

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

...

答案 1 :(得分:4)

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

答案 2 :(得分:2)

C#使用延迟检查,所以你的第一个代码应该没问题(当然||改为&&&&&当然!)

更新 - 这是: http://msdn.microsoft.com/en-gb/library/6373h346.aspx “ 操作

x || ÿ

对应于操作

x | ÿ

除了如果x为真,则不计算y(因为无论y的值是多少,OR运算的结果都为真)。这被称为“短路”评估。 “

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

答案 3 :(得分:1)

我将添加强制性建议,即必须挖掘公共财产的层次通常意味着你暴露了太多的内部状态,并且你正在遍历的类应该为你做这项工作。我还希望一个对象确保它的属性首先不返回null。

当然有优势,但这些都是很好的经验法则。