How to avoid multiple if null checks [duplicate]

2019-03-16 08:47发布

Possible Duplicates:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is null

i have to do a lookup in a deep object model like this:

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

is there anyway to evalute this and return null if any of the chain is null (organizationalunit, parent, head, etc), without having to do a

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

标签: c# null
5条回答
Emotional °昔
2楼-- · 2019-03-16 09:03

Have you heard of the Law of Demeter?

Chaining such long sequences of calls is not a good idea. It creates awful dependencies between classes that you don't need.

In your example, the class containing p becomes dependent of five other classes. I suggest you simplify your code and make each class check for nulls at a single level, in their own context of knowledge.

查看更多
可以哭但决不认输i
3楼-- · 2019-03-16 09:07

To answer the question in your title, you can avoid by applying the 'law of demeter' and creating a method called GetHeadOfParentOrganizationalUnit()

I'm not sure if the solution applies for your specific case, but it's worth a look if you can eliminate all those null checks.

See also: a link

查看更多
Juvenile、少年°
4楼-- · 2019-03-16 09:15

You are looking for the null-safe dereference operator ?. (also known as safe navigation) that some languages (e.g. Groovy) have, but unfortunately C# does not have this operator.

Hopefully it will be implemented one day....

See also this post by Eric Lippert. The syntax he proposes there is .?.

查看更多
Anthone
5楼-- · 2019-03-16 09:21

You can use basic exception handling as well to catch that. I'm not crazy about that solution, but it is an option. If these nested nulls are normal operation, exceptions are probably not the right answer:

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.");
        }

    }

}
查看更多
叼着烟拽天下
6楼-- · 2019-03-16 09:25

Check out this article. It presents a great solution that allows you to write things like that:

p.With(x => x.OrganisationalUnit)
 .With(x => x.Parent)
 .With(x => x.Head)
 .With(x => x.CurrentAllocation
 .With(x => x.Person);
查看更多
登录 后发表回答