first timer
first timer

Reputation: 753

How to perform Zip operation with null array

I'm experimenting with Zip operations in C#, like described here. Considering this code snippet:

int[] numbers = new[] { 1, 2, 3, 4 };
string[] words = new string[] { "one", "two", "three", "four" };

var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w });
foreach (var nw in numbersAndWords)
{
    Console.WriteLine(nw.Number + nw.Word);
}

What is a proper way to avoid System.ArgumentNullException in case one of the components are null?
For example, initializing words to null, like this

int[] numbers = new[] { 1, 2, 3, 4 };
string[] words = null;

// The next line won't work
var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w });


Obs: I'm actually working with Directory.EnumerateDirectories and Directory.EnumerateFiles instead of int[] and string[].

Upvotes: 4

Views: 2146

Answers (2)

Alexei Levenkov
Alexei Levenkov

Reputation: 100527

Zip is not very useful to work with empty sequences as it will return empty sequence as a result (it returns sequence based on shorter length). You may as well check for that instead:

 var result = numbers == null || words==null ? 
      Enumerable.Repeat(new { Number = 0, Word = "" },0) :
      numbers.Zip(words, (n, w) => new { Number = n, Word = w });

Based on your possible usage I don't see how Zip'ing Directory and Files would be useful (ignoring painful "Access denied" and other IO Exceptions). Possibly you want to have a list of files along with the parent directory. Approximate code below (get all files for each directory, pair each file with directory info, flatten):

  var directories = ....
  var filesAndDir = directories
     .Select(dir => Directory.EnumerateFiles(dir).Select{file => new {dir, file})
     .SelectMany(r=>r); 

Upvotes: 0

Alex
Alex

Reputation: 13224

The following is kinda ugly, but you could use the null coalescing operator ?? like this:

var numbersAndWords = 
  (numbers ?? Enumerable.Empty<int>()).Zip(
        (words ?? Enumerable.Empty<string>()), 
        (n, w) => new { Number = n, Word = w });

Or create an extension method that does the same (you may want to come up with a better name than OrEmpty):

public static class MyEnumerableExtensions
{
    public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> self)
    {
        return self ?? Enumerable.Empty<T>();
    }
}

var numbersAndWords = numbers.OrEmpty()
    .Zip(words.OrEmpty(), (n, w) => new { Number = n, Word = w });

Upvotes: 5

Related Questions