20

例如,如果我想调用以下内容: person.Head.Nose.Sniff() 那么,如果我想安全,我必须执行以下操作:

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

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

4

9 回答 9

19

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

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

另请注意,您所做的事情违反了开发软件的设计指南,即Demeter 法则

于 2010-09-13T14:57:43.420 回答
15

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

在 C# 6 中,您可以使用空条件运算符 ?

代码示例

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

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

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

    public bool PerformNullCheckVersion2(Person person)
    {
        return person?.Head?.Nose?.Sniff() ?? false;
    }

??合并运算符,与您的问题无关。

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

于 2016-07-10T20:08:47.173 回答
6

下面是另一个实现,与前面提到的 Fluent Parameter Validation 类似: Chained null checks and the Maybe monad

于 2010-09-13T15:19:12.723 回答
4

不是真的,除此之外

 if (person != null && person.Head != null && person.Head.Nose != null) 
于 2010-09-13T14:57:20.437 回答
3

您可以使用空对象而不是空值。Sniff如果调用链中的任何对象都是空对象,则什么也不做。

这不会引发异常:

person.Head.Nose.Sniff(); 

您的 null 类可能如下所示(您也可以将它们用作单例并具有用于IPerson,IHead和的接口INose):

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 中有一个操作符

person:Head:Nose:Sniff; 
于 2010-09-13T15:11:37.767 回答
2

您可以使用流畅的参数验证

于 2010-09-13T15:03:36.757 回答
1

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

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

请注意,从技术上讲,您可以使用表达式树执行类似的空值检查。您的方法将具有如下签名:

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

...这将允许您编写如下所示的代码:

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

但这将涉及反思,并且与该方法相比,通常更难以以任何深入的方式遵循&&

于 2010-09-13T15:09:14.700 回答
1
if (person?.Head?.Nose != null) person.Head.Nose.Sniff();   
于 2021-06-21T14:27:17.100 回答
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;
    } 
}
于 2010-09-13T15:04:13.963 回答