JD Davis
JD Davis

Reputation: 3720

More graceful solution to nested Linq queries?

I have a set of nested linq queries that are used to get a property from a list of properties. It works great as-is, but it has one caveat. I have to put in error handling just in-case there isn't a suitable match. Is there are similar method of accomplishing what the following code does without having to use a try-catch block?

try
{
    organization =
    _orgs.FirstOrDefault(n => 
        n.OrganizationFields.FirstOrDefault(nn => 
            nn.Key == "customer_id").Value.ToString() == id);
}
catch (InvalidOperationException)
{
    return null;
}
catch (NullReferenceException)
{
    return null;
}

Upvotes: 1

Views: 84

Answers (2)

Ivan Stoev
Ivan Stoev

Reputation: 205739

I'm not sure why you need to catch InvalidOperationException, so I'll ignore it. What about NullReferenceException, I assume it can only be generated by the FirstOrDefault(...).Value call (if you follow the best practices, none of the _orgs, n.OrganizationFields or Value should be null).

If the above assumptions are correct, the following should be the equivalent of the sample code w/o a need of exception handlers

organization = _orgs.FirstOrDefault(n => n.OrganizationFields
    .Any(nn => nn.Key == "customer_id" && nn.Value.ToString() == id));

As per your comment, if the Value can be null, then either use nn.Value?.ToString() == ... in C#6, or nn.Value != null && nn.Value.ToString() == ... in pre C#6.

Upvotes: 1

Eric J.
Eric J.

Reputation: 150148

If you are using C# 6, you can use the Null Conditional Operator.

organization =
_orgs?.FirstOrDefault(n => 
    n.OrganizationFields?.FirstOrDefault(nn => 
        nn.Key == "customer_id")?.Value.ToString() == id);

Here's a complete program that shows it in action

class Bar
{
    public string Text { get; set; }
}

class Foo
{
    public List<Bar> Bars { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo(); // Note that foo.Bars is still null

        string text = foo.Bars?.FirstOrDefault()?.Text;

        Console.WriteLine(text);
    }
}

Upvotes: 3

Related Questions