tags:

views:

116

answers:

5

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 . . .     
+4  A: 

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 .?.

Mark Byers
+2  A: 

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.

CesarGon
@CesarGon - agree but taken over a large code base, can't refactor it all in a day :)
ooo
@ooo: I understand. In that case, I think you need to use the ugly chain of null checks. I'd try to encapsulate this in a private method so that dependencies are isolated and easily recognisable.
CesarGon
A: 

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

Gishu
@Gishu - but then the function GetHeadofParent . . would just have that same nested null check
ooo
@oooo - Not really you step in one level at a time. Each class only talks to its immediate collaborator, you don't hack away into the internals the collaborator to tear away some nested state... *read up on the law of demeter*. From wikipedia - A disadvantage of the Law of Demeter is that it sometimes requires writing a large number of small "wrapper" methods to propagate method calls to the components. Furthermore, a class's interface can become bulky as it hosts methods for contained classes, resulting in a class without a cohesive interface. But this might also be a sign of bad OO design.
Gishu
+2  A: 

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);
Thomas Levesque
A: 

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

    }

}
PatrickV
Invoking the exception handling system seems excessive for normal operations; however like you said it is a solution, thinking outside the box.
John K
@John K: I agree - the only way I'd ever really consider this is if any nested nulls represented a "broken" state. Plus there's the problem of not knowing which dereference broke the system, and the performance hit. But it is a tool in the box...
PatrickV