3

I have a method that has many many statements like this:

employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value;

(This is a made up structure. The actual structure is based off of 2.3 HL7 XML and is far more complex and full of pointless objects.)

So my problem is that any one of these values can be null. If I don't check that then when I try to get the next value in the chain it will throw an exception.

Obviously I could do something like this:

if (contract.EMPLOYEE != null)
 if (contract.EMPLOYEE.NAME.SUBNAME != null)
  if (contract.EMPLOYEE.NAME.FAMILYNAME != null)
   if (contract.EMPLOYEE.NAME.FAMILYNAME.NAMEPART1 != null)
     employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value;  

But that is a lot of checks for each time I need to set a value. (And the object tree changes a lot so I cannot do a check it once and be done system.)

Maybe the better way is to do this:

try
{
   employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value;
}
catch
{}

(Note if the value is not there then I am fine to not have nothing done.)

However, this is a bit messy still. I have 14 items to set in this method alone and many many more to come.

Is there a way I can abstract this so I can just do my setters and little else?

I thought of a method call that would do the checks/try statement, but if I pass in file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value it will try to resolve it while I pass it (thus giving me an exception).

Is there some other (clean) way? (Maybe an extension method would work?) I would be grateful to any ideas.


Note: I ended up just doing this for each line:

try { employee.LastName = file.EMPLOYEE.NAME.SUBNAME.FAMILYNAME.NAMEPART1.Value; } catch (System.NullReferenceException) { }

It seems more readable than the lambda system.

Vaccano
  • 78,325
  • 149
  • 468
  • 850
  • 1
    See http://stackoverflow.com/questions/665554/extending-the-c-sharp-coalesce-operator – Muhammad Hasan Khan Nov 07 '11 at 16:28
  • 1
    Groovy has the ? null check symbol, so file?.EMPLOYEE?.NAME?.SUBNAME?.FAMILYNAME?.NAMEPART1?.Value will return null. I am still looking for the C# equivalent. – Arcturus Nov 07 '11 at 16:29
  • 1
    The better way is most assuredly not the `try/catch` that swallows not only the `NullReferenceException` you anticipate but also everything else. Sure, the code is simpler, but it is still a worst practice to use exceptions in such a manner. – Anthony Pegram Nov 07 '11 at 16:42

1 Answers1

4

How about this:

static class Coalesce
{
    static public TResult C<T, TResult>(this T obj, Func<T, TResult> func)
        where TResult : class
    {
        if (obj != null)
            return func(obj);
        return null;
    }
}

Used like this:

employee.LastName =
    file.C(o => o.EMPLOYEE)
        .C(o => o.NAME)
        .C(o => o.SUBNAME)
        .C(o => o.FAMILYNAME)
        .C(o => o.NAMEPART1)
        .C(o => o.Value); 

This will return null if any of the properties in the chain are null.

This was inspired by the question Extending the C# Coalesce Operator, but I used a slightly different approach. At the expense of a slightly longer call syntax, my extension class is simpler and there is no limit to the number of links in the chain.

You can also combine it with the ?? operator to assign a default:

class Foo { public Bar MyBar { get; } }
class Bar { public Baz MyBaz { get; } }
class Baz { }

Baz baz = foo.C(o => o.MyBar).C(o => o.MyBaz) ?? new Baz();
Community
  • 1
  • 1
Igby Largeman
  • 16,495
  • 3
  • 60
  • 86