7

I have several plain old C# objects that are returned by an API, and have several layers of POCOs nested within them. I need to access fields contained deep within these structures, but because the API leaves these nested objects as null when data is missing, I find myself having to do lots of null checks just to get at the field I really want.

if(obj != null && obj.Inner != null && obj.Inner.Innerer != null) { ... }

The shortest form I've come up with is using the ternary operator.

obj != null && obj.Inner != null && obj.Inner.Innerer != null ? obj.Inner.Innerer.Field : null;

Does C# have any way to do this without having to write out all those comparisons? I'd really like something short and simple like:

obj.Inner.Innerer.Field ?? null;

But that only checks Field for null.

Syon
  • 7,205
  • 5
  • 36
  • 40
  • How about [this](http://stackoverflow.com/questions/17657942/nice-way-to-avoid-null-checks-in-ifs/17663536#17663536)? – rene Jul 26 '13 at 17:25
  • Hmm, the `f` method is definitely too messy. It makes the line of code shorter, but I'd say ternary is easier to understand. The `tc` method is pretty close, but throws an exception in the method which is a performance penalty (especially compared to a null check). So close, but not exactly what I'd hope for. – Syon Jul 26 '13 at 17:39
  • An idea is that you could try to directly access Inner.Innerer.Field while trying to catch a null exception. If anything along the road is null, the exception is caught and you return null. Otherwise you return the value. – KappaG3 Jul 26 '13 at 18:00
  • No, exceptions won't be a "performance penalty" on any modern computers. It's for "exceptional behaviors", you won't loop on the exception million of times. – Pierre-Luc Pineault Jul 26 '13 at 18:11
  • @KappaG3 That would make for try catches all over the place, I'd rather avoid lots of extra code just for checking null. – Syon Jul 26 '13 at 18:13
  • 1
    @KappaG3 That is only possible if the getter is just a return of such backing field but there are implementation out in the wild that do a lot of work in the get method. – rene Jul 26 '13 at 18:14
  • This is definitely a code smell, but I think you're going about it in the wrong way. You should only be dealing with Innerer or even just Field. Please see Law of Demeter: http://en.wikipedia.org/wiki/Law_of_Demeter. If this is working with an API that you do not control abstract the ugliness into a extension, helper, or wrapper class. – bodhizero Jul 26 '13 at 18:37
  • Yes, this is an API I have no control over. And this issue came up because I'm working on the wrapper for it. – Syon Jul 26 '13 at 18:48
  • @Syon, then I'd say how you're doing it is fine. Trying to come up with some fancy solution to make your code appear more elegant will only make it harder for others to understand. – bodhizero Jul 26 '13 at 19:07
  • @Martin Smith: Affirmative. Guess my initial search was insufficient. Close as duplicate if necessary. – Syon Jul 26 '13 at 22:03

2 Answers2

1

Please have a look at this very clever and elegant solution:

http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad

RX_DID_RX
  • 4,113
  • 4
  • 17
  • 27
  • Interesting, but to make this chaining work I would need to modify the objects return from the API, and I have no control over them. – Syon Jul 26 '13 at 19:09
0

It's not beautiful, but you could write accessor functions in your code that would encapsulate the null checks so you only have to do it in one place. E.g.

Innerer GetInnerer()
{
  if(obj != null && obj.Inner != null && obj.Inner.Innerer != null)
  {
    return obj.Inner.Innerer;
  }

  return null;
}

That way you could call it like this: if (myObject.GetInnerer() != null).... You would have to create a number of these functions, but at least it would move the 'goreyness' of null checking to a single location.

edtheprogrammerguy
  • 5,957
  • 6
  • 28
  • 47