例如,如果我想调用以下内容:
person.Head.Nose.Sniff()
那么,如果我想要安全,我必须做以下事情:
if(person != null)
if(person.Head != null)
if(person.Head.Nose != null)
person.Head.Nose.Sniff();
有没有更简单的方法来制定这个表达式?
答案 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类可能如下所示(您也可以将它们用作单例并具有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中有一个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();
这需要某种基础class
或interface
。
public abstract class BodyPart
{
public bool IsDecapitated { get; private set; }
public BodyPart(bool isDecapitated)
{
IsDecapitated = isDecapitated;
}
}