c# - Returning default values for null properties, when the parent of these properties can or can not be null

StackOverflow https://stackoverflow.com/questions/16524728

  •  29-05-2022
  •  | 
  •  

سؤال

So I didn't find any elegant solution for this, either googling or throughout stackoverflow. I guess that I have a very specific situation in my hands, anyway here it goes:

I have a object structure, which I don't have control of, because I receive this structure from an external WS. This is quite a huge object, with various levels of fields and properties, and this fields and properties can or can't be null, in any level. You can think of this object as an anemic model, it doesn't have behaviour, just state.

For the purpose of this question, I'll give you a simplified sample that simulates my situation:

Class A
  PropB1
    PropC11
      PropLeaf111
    PropC12
      PropLeaf112
  PropB2
    PropC21
      PropLeaf211
    PropC22
      PropLeaf221

So, throughout my code I have to access a number of these properties, in different levels, to do some math in order to calculate what I need. Basically for each type of calculation that I have to do, I have to test each level of the properties that I need, to check if it's not null, in which case I would return (decimal) 0, or any other default value depending on the business logic.

Sample of a math that I have to do with it:

var value = 0;
if (objClassA.PropB1 != null && objClassA.PropB1.PropC11 != null) {
  var leaf = objClassA.PropB1.PropC11.PropLeaf111;
  value = leaf.HasValue ? leaf.Value : value;
}

Just to be very, the leaf properties of this structure would always be primitives, or nullable primitives in which case I give the proper treatment. This is "the logic" that I have to do for each property that I need, and sometimes I have to use quite some of them. Also the real structure is quite bigger, so the number of verifications that I would need to do, would also be bigger for each necessary property.

Now, I came up with some ideas, none of them I think is ideal:

  1. Create methods to gather the properties, where it would abstract any necessary verification, or the logic to get default values. The drawback is that it would have, in my opinion, quite some duplicated code, since the verifications and the default values would be similar for some groups of fields.
  2. Create a single generic method, where it receives a object, and a lamba function that access the required field. This method would try to execute the function and return it's result, and in case of an NullReferenceException, it would return a default value. The bright side of this one, is that it is realy generic, I just have to pass lambdas to access the properties, and the method would handle any problem. The drawback of it, is that I am using try -> catch to control logic, which is not the purpose of it, and the code might look confusing for other programmers that would eventually give maintenance to it.
  3. Null Object Pattern, this would be the most elegant solution, I guess. It would have all the good points if it was a normal case. But the thing is the impact of providing Null Objects for this structure. Just to give a bit more of context, the software that I am working on, integrates with government's services, and the structure that I am working with, which is in the government's specifications, have some fields where null have some meaning which is different from a default value like "0". Also this specification changes from time to time, and the classes are generated again, and the post processing that I would have to do to create Null Objects, would also need maintenance, which seems a bit dangerous for me.

I hope that I made myself clear enough.

Thanks in advance.

Solution

This is a response as to how I solved my problem, based on the accepted answer.

I'm quite new to C#, and this kind of discution that was linked really helped me to come up with a elegant solution in many aspects. I still have the problem that depending where the code is executed, it uses .NET 2.0, but I also found a solution for this problem, where I can somewhat define extension methods: https://stackoverflow.com/a/707160/649790

And for the solution itself, I found this one the best: http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad

I can basically access the properties this way, and just do the math:

objClassA.With(o => o.PropB1).With(o => PropC11).Return(o => PropLeaf111, 0);

For each property that I need. It still isn't just:

objClassA.PropB1.PropC11.PropLeaf111

ofcourse, but it is far better that any solution that I found so far, since I was unfamiliar with Extension Methods, I really learned a lot.

Thanks again.

هل كانت مفيدة؟

المحلول

There is a strategy for dealing with this, involving the "Maybe" Monad.

Basically it works by providing a "fluent" interface where the chain of properties is interrupted by a null somewhere along the chain.

See here for an example: http://smellegantcode.wordpress.com/2008/12/11/the-maybe-monad-in-c/

And also here:

http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad http://mikehadlow.blogspot.co.uk/2011/01/monads-in-c-5-maybe.html

It's related to but not quite the same as what you seem to need; however, perhaps it can be adapted to your needs. The concepts are fairly fundamental.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top