Eminem
Eminem

Reputation: 7484

Check for null in foreach loop

Is there a nicer way of doing the following:
I need a check for null to happen on file.Headers before proceeding with the loop

if (file.Headers != null)
{
  foreach (var h in file.Headers)
  {
   //set lots of properties & some other stuff
  }
}

In short it looks a bit ugly to write the foreach inside the if due to the level of indentation happening in my code.

Is something that would evaluate to

foreach(var h in (file.Headers != null))
{
  //do stuff
}

possible?

Upvotes: 151

Views: 137547

Answers (8)

Eddie
Eddie

Reputation: 200

The best answer in the year 2022 should be:

foreach (var h in file.Headers ?? Enumerable.Empty<T>())
{
    //do stuff
}

Replace T with your data type. if file.Headers is an array, use Array.Empty<T>() instead of Enumerable.Empty<T>()

Upvotes: 7

Jon Skeet
Jon Skeet

Reputation: 1499800

Just as a slight cosmetic addition to Rune's suggestion, you could create your own extension method:

public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}

Then you can write:

foreach (var header in file.Headers.OrEmptyIfNull())
{
}

Change the name according to taste :)

Upvotes: 179

Rune FS
Rune FS

Reputation: 21742

Assuming that the type of elements in file.Headers is T you could do this

foreach(var header in file.Headers ?? Enumerable.Empty<T>()){
  //do stuff
}

this will create an empty enumerable of T if file.Headers is null. If the type of file is a type you own I would, however, consider changing the getter of Headers instead. null is the value of unknown so if possible instead of using null as "I know there are no elements" when null actually(/originally) should be interpreted as "I don't know if there are any elements" use an empty set to show that you know there are no elements in the set. That would also be DRY'er since you won't have to do the null check as often.

EDIT as a follow up on Jons suggestion, you could also create an extension method changing the above code to

foreach(var header in file.Headers.OrEmptyIfNull()){
  //do stuff
}

In the case where you can't change the getter, this would be my own preferred since it expresses the intention more clearly by giving the operation a name (OrEmptyIfNull)

The extension method mentioned above might make certain optimizations impossible for the optimizer to detect. Specifically, those that are related to IList using method overloading this can be eliminated

public static IList<T> OrEmptyIfNull<T>(this IList<T> source)
{
    return source ?? Array.Empty<T>();
}

Upvotes: 114

Andrei Karcheuski
Andrei Karcheuski

Reputation: 3306

Using Null-conditional Operator and ForEach() which works faster than standard foreach loop.
You have to cast the collection to List though.

   listOfItems?.ForEach(item => // ... );

Upvotes: 31

N. Kudryavtsev
N. Kudryavtsev

Reputation: 4071

For some cases I'd prefer slightly another, generic variant, assuming that, as a rule, default collection constructors return empty instances.

It would be better to name this method NewIfDefault. It can be useful not only for collections, so type constraint IEnumerable<T> is maybe redundant.

public static TCollection EmptyIfDefault<TCollection, T>(this TCollection collection)
        where TCollection: class, IEnumerable<T>, new()
    {
        return collection ?? new TCollection();
    }

Upvotes: 0

Wolfgang Ziegler
Wolfgang Ziegler

Reputation: 1685

I am using a nice little extension method for these scenarios:

  public static class Extensions
  {
    public static IList<T> EnsureNotNull<T>(this IList<T> list)
    {
      return list ?? new List<T>();
    }
  }

Given that Headers is of type list, you can do following:

foreach(var h in (file.Headers.EnsureNotNull()))
{
  //do stuff
}

Upvotes: 3

Marc Gravell
Marc Gravell

Reputation: 1062510

Frankly, I advise: just suck up the null test. A null test is just a brfalse or brfalse.s; everything else is going to involve much more work (tests, assignments, extra method calls, unnecessary GetEnumerator(), MoveNext(), Dispose() on the iterator, etc).

An if test is simple, obvious, and efficient.

Upvotes: 34

Tamir
Tamir

Reputation: 3901

the "if" before the iteration is fine, few of those "pretty" semantics can make your code less readable.

anyway, if the indentation disturbs your, you can change the if to check:

if(file.Headers == null)  
   return;

and you'll get to the foreach loop only when there is a true value at the headers property.

another option I can think about is using the null-coalescing operator inside your foreach loop and to completely avoid null checking. sample:

List<int> collection = new List<int>();
collection = null;
foreach (var i in collection ?? Enumerable.Empty<int>())
{
    //your code here
}

(replace the collection with your true object/type)

Upvotes: 19

Related Questions