【问题标题】:How to avoid multiple if null checks [duplicate]如何避免多个 if null 检查[重复]
【发布时间】:2010-10-10 02:29:52
【问题描述】:

可能的重复:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is null

我必须像这样在深层对象模型中进行查找:

  p.OrganisationalUnit.Parent.Head.CurrentAllocation.Person;

如果任何一个链为空(组织单元、父级、头部等),是否有评估这个并返回空,而不必做一个

if (p.org == null && p.org.Parent == null && p.org.Parent.Head . . .     

【问题讨论】:

  • 尽量避免这种查找;详情请看我下面的回答。

标签: c# null


【解决方案1】:

您正在寻找某些语言(例如 Groovy)具有的 null 安全取消引用运算符 ?.(也称为安全导航),但不幸的是 C# 没有此运算符。

希望有一天能实现....

另请参阅 Eric Lippert 的 this post。他建议的语法是.?

【讨论】:

【解决方案2】:

你听说过Law of Demeter吗?

链接如此长的调用序列并不是一个好主意。它在你不需要的类之间创建了可怕的依赖关系。

在您的示例中,包含p 的类依赖于五个 其他类。我建议你简化你的代码,让每个类在他们自己的知识上下文中在一个级别上检查空值。

【讨论】:

  • 同意,但接管了一个庞大的代码库,不能在一天之内全部重构:)
  • @ooo:我明白了。在这种情况下,我认为您需要使用丑陋的空检查链。我会尝试将其封装在一个私有方法中,以便隔离并且易于识别。
【解决方案3】:

查看this article。它提供了一个很棒的解决方案,让您可以编写这样的内容:

p.With(x => x.OrganisationalUnit)
 .With(x => x.Parent)
 .With(x => x.Head)
 .With(x => x.CurrentAllocation
 .With(x => x.Person);

【讨论】:

    【解决方案4】:

    要回答标题中的问题,您可以通过应用“demeter 定律”并创建一个名为 GetHeadOfParentOrganizationalUnit() 的方法来避免

    我不确定该解决方案是否适用于您的具体情况,但如果您可以消除所有这些空检查,则值得一看。

    另请参阅:a link

    【讨论】:

    • 然后是函数 GetHeadofParent 。 .只会有相同的嵌套空检查
    • @oooo - 并不是你一次进入一个级别。每个类只与它的直接合作者对话,你不会侵入合作者的内部来撕掉一些嵌套状态...阅读 demeter 法则。来自维基百科 - 得墨忒耳定律的一个缺点是它有时需要编写大量小型“包装器”方法来将方法调用传播到组件。此外,一个类的接口可能会变得庞大,因为它承载了包含的类的方法,从而导致一个没有内聚接口的类。但这也可能是糟糕的 OO 设计的标志。
    【解决方案5】:

    您也可以使用基本的异常处理来捕获它。我对那个解决方案并不疯狂,但它是一种选择。如果这些嵌套的空值是正常操作,异常可能不是正确的答案:

    public class A
    {
    }
    public class B
    {
       public A a;
    }
    public class C
    {
        public B b;
    }
    class Program
    {
        static A GetA(C c)
        {
            A myA;
            try
            {
                myA = c.b.a;
            }
            catch
            {
                myA = null;
            }
            return myA;
        }        
    
        static void Main(string[] args)
        {
            C theC = new C();
            theC.b = new B();
            theC.b.a = new A();
            A goodA = GetA(theC);
            if (goodA != null)
            {
                Console.WriteLine("Expected nominal path.");
            }
            else
            {
                Console.WriteLine("Unexpected nominal path.");
            }
            theC.b.a = null;
            A badA = GetA(theC);
            if (badA == null)
            {
                Console.WriteLine("Expected off-nominal path.");
            }
            else
            {
                Console.WriteLine("Unexpected off-nominal path.");
            }
    
        }
    
    }
    

    【讨论】:

    • 调用异常处理系统对于正常操作来说似乎是多余的;但是就像你说的那样,这是一个解决方案,跳出框框思考。
    • @John K:我同意——我真正考虑过的唯一方法是,如果任何嵌套的空值表示“损坏”状态。另外还有一个问题是不知道哪个取消引用破坏了系统,并且性能受到影响。但它是盒子里的工具......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 2019-03-27
    • 2016-01-29
    • 1970-01-01
    相关资源
    最近更新 更多