开发者

Proposed solution for checking for nulls in an object hierarchy

开发者 https://www.devze.com 2022-12-21 15:39 出处:网络
Revisiting the subject of a previous post I would like some feedback on a proposed solution. In my code (C# 3.0) I need to handle application forms provided to me by a service in an object structure

Revisiting the subject of a previous post I would like some feedback on a proposed solution.

In my code (C# 3.0) I need to handle application forms provided to me by a service in an object structure from a large deserialized XML document. The form can contain many different types of data so I need to do a lot of null checks to see if data is present.

For example there might be a value for:

ApplicationForm.EmployeeInfo.PersonalInfo.Name

And to check for a non-null value here I must check every step on the way down.

I want avoid long if statements and try-catch blocks so my solution is the extension method

public static T NN<T>(this T obj) where T : class, new()
{
    return obj ?? new T();
}

which can be used as

if (ApplicationForm.NN().EmployeeInfo.NN().PersonalInfo.NN().Name != null)

This way if the next step on the way down the hierarchy is not initialized it is temporarily new'ed and returned. The NN (Not Null) method returns the de开发者_StackOverflow中文版fault object instead of null which in my case is perfectly suitable. And when working with xsd-tool generated object structures where I need to check the "~Specified" property of all optional elements it comes in handy.

Now my question is whether I am missing something that makes this otherwise good solution a poor choice. Is the new'ing of so many empty default objects too heavy on memory or performance or are there other issues?

A quick but of course non-conclusive test I did showed no significant performance hit.


Ask a programmer what she does, your usual answer is "hmm, programming?".
Wrong.
I had a CS professor for a boss for a while. He claimed that programmers write code less than 10% of their time. Most time it spent reading and debugging code. Therefore, he insisted we must avoid writhing "chains" of properties or function calls. This is very relevant to your case - the NN hack may seem nice and saves you a few minutes today, but will cost more than a few in the future.


I agree that this is longer:

if (ApplicationForm != null && 
    ApplicationForm.EemployeeInfo != null && 
    ApplicationForm.EemployeeInfo.PersonalInfo != null &&
    ApplicationForm.EemployeeInfo.PersonalInfo.Name != null) {
    // ...
} 

but it also more readable; if I was to maintain your application, I would be grateful to you for doing the checks in a standard way.
I would go for readability, even at the expense of longer code and even if there is no performance hit in your solution.


I wrote a blog post a few days ago about a way to automate null checks using Linq expressions :

http://www.thomaslevesque.com/2010/02/21/automating-null-checks-with-linq-expressions/

I came up with a solution that allows you to write something like that :

string name = ApplicationForm.NullSafeEval(a => a.EmployeeInfo.PersonalInfo.Name);

The expression tree is analysed and rewritten to add null checks for each level of the property path

However, although this solution works, I wouldn't recommend using it if performance is critical...


Use the Null monad. It can be in the same file or a different file so long as you using it.

public static class NullMonad {
    public static TResult SelectMany<TIn, TOut, TResult>(this TIn @in, Func<TIn, TOut> remainder, Func<TIn, TOut, TResult> resultSelector)
        where TIn : class
        where TOut : class
        where TResult : class {
        var @out = @in != null ? remainder(@in) : null;
        return @out != null ? resultSelector(@in, @out) : null;
    }
}

Then you can use LINQ:

var salary = from form in applicationForm
             from info in form.employeeInfo
             from cond in info.workingConditions
             select cond.salary

This will return the salary if it exists, or null if any of the prior statements result to null, without throwing an exception. It reduces the repetition of hand-checking each variable. It also avoids the overhead of creating all the unused "NN" objects.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号