在C#中,是否有一种检查多级空引用的简洁方法

时间:2010-09-13 14:55:01

标签: c# null reference-type

例如,如果我想调用以下内容: person.Head.Nose.Sniff() 那么,如果我想要安全,我必须做以下事情:

if(person != null)
    if(person.Head != null)
        if(person.Head.Nose != null)
            person.Head.Nose.Sniff();

有没有更简单的方法来制定这个表达式?

9 个答案:

答案 0 :(得分:18)

首先,您可以利用布尔逻辑运算符中的短路,并执行以下操作:

if (person != null && person.Head != null && person.Head.Nose != null)
{
    person.Head.Nose.Sniff();
}

另请注意,您所做的事情与开发称为Law of Demeter的软件的设计指南背道而驰。

答案 1 :(得分:12)

  

有没有更简单的方法来制定这个表达式?

使用C#6,您可以使用null-conditional operator boolean playedAtLeastOnce; @Override public void onPrepared(MediaPlayer mp) { mp.start(); playedAtLeastOnce = true; } public boolean isPaused() { if (!mMediaPlayer.isPlaying && playedAtLeastOnce) return true; else return false; // or you can do it like this // return !mMediaPlayer.isPlaying && playedAtLeastOnce; }

代码示例

这是您打包到方法中的原始代码,并假设?始终返回Sniff()

true

这是用C#6空条件运算符重写的代码:

    public bool PerformNullCheckVersion1(Person person)
    {
        if (person != null)
            if (person.Head != null)
                if (person.Head.Nose != null)
                    return person.Head.Nose.Sniff();
        return false;
    }

public bool PerformNullCheckVersion2(Person person) { return person?.Head?.Nose?.Sniff() ?? false; } null-coalescing operator,与您的问题无关。

有关完整示例,请参阅: https://github.com/lernkurve/Stackoverflow-question-3701563

答案 2 :(得分:7)

这是另一个实施方案,与前面提到的Fluent参数验证一致:Chained null checks and the Maybe monad

答案 3 :(得分:4)

不是真的,除了

 if (person != null && person.Head != null && person.Head.Nose != null) 

答案 4 :(得分:3)

您可以使用null objects代替空值。如果调用链中的任何对象都是空对象,则Sniff将不执行任何操作。

这不会引发异常:

person.Head.Nose.Sniff(); 

您的null类可能如下所示(您也可以将它们用作单例并具有IPersonIHeadINose的接口):

class NullPerson : Person {
  public override Head Head { get { return new NullHead(); }
}
class NullHead : Head {
  public override Nose Nose { get { return new NullNose(); }
}
class NullNose : Nose {
  public override void Sniff() { /* no-op */ }
}

作为旁注,在Oxygene中有一个operator

person:Head:Nose:Sniff; 

答案 5 :(得分:2)

答案 6 :(得分:1)

最好的方法是使用&&运算符而不是嵌套的if语句:

if (person != null && person.Head != null && person.Head.Nose != null)
{
    person.Head.Nose.Sniff();
}

请注意,技术上可以执行类似的空检查using an expression tree。你的方法会有这样的签名:

static bool IsNotNull<T>(Expression<Func<T>> expression);

...这将允许你编写类似这样的代码:

if (IsNotNull(() => person.Head.Nose))
{
    person.Head.Nose.Sniff();
}

但这会涉及反思,与&&方法相比,通常会以任何形式更难以遵循。

答案 7 :(得分:1)

if (person?.Head?.Nose != null) person.Head.Nose.Sniff();   

答案 8 :(得分:0)

我会摆脱对null的任何使用并做这样的事情:

((Nose)person.BodyParts[BodyPart.Nose]).Sniff();

这需要某种基础classinterface

public abstract class BodyPart
{
    public bool IsDecapitated { get; private set; }

    public BodyPart(bool isDecapitated)
    {
        IsDecapitated = isDecapitated;
    } 
}