Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Code Simplification Query: The Null Container and the Foreach Loop

Tags:

c#

I frequently have code that looks something like this:

if (itm != null)
{
    foreach (type x in itm.subItems())
    {
        //dostuff
    }
}
//do more stuff

In situations where //do more stuff is omitted, it is very easy to avoid the extra foreach loop. By exitting scope using the appropriate command (depending on what is going on, this generally would mean a return statement or a continue statement).

This type of thing tends to result in arrow code. I currently have a few ways to deal with this:

  • Use code like itm = itm == null ? itm.subItems() : emptyArray
  • Allow arrow code
  • Use goto
  • Use evil scoping hacks (wrapping the whole thing, if statement in all, in a scope and then breaking out of it). In my opinion evil scoping hacks are basically equivalent to goto except uglier and harder to read, so I don't consider this a valid solution.
  • Refactor some of the chunks into new methods. There are in fact a few cases where this probably is a good solution, but mostly it's not appropriate since the null references are mainly error conditions from MS-functions.

Anyone care to offer a response on what approaches are considered preferable?

like image 876
Brian Avatar asked Mar 13 '09 21:03

Brian


1 Answers

If you're using C# 3, you could always write an extension method:

public static IEnumerable<SubItem> SafeSubItems(this ItemType item)
{
     return item == null ? Enumerable.Empty<SubItem> : source.SubItems();
}

Then just write:

foreach (SubItem x in itm.SafeSubItems())
{
    // do stuff
}
// do more stuff

The key thing is that extension methods can be called even "on" null references.

What would be nice would be a "null-safe dereferencing" operator, so we could write:

// Not valid C# code!
foreach (SubItem x in itm?.SubItems() ?? Enumerable.Empty<SubItem>())
{
}

Or just define an EmptyIfNull extension method on IEnumerable<T> and use

// Not valid C# code!
foreach (SubItem x in (itm?.SubItems()).EmptyIfNull())
{
}
like image 134
Jon Skeet Avatar answered Oct 20 '22 12:10

Jon Skeet