如何使用空数组执行 Zip 操作

How to perform Zip operation with null array

我正在 C# 中试验 Zip 操作,如 here 所述。考虑这个代码片段:

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);
}

如果其中一个组件是 null,避免 System.ArgumentNullException 的正确方法是什么?
比如初始化words为null,像这样

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:我实际上正在使用 Directory.EnumerateDirectoriesDirectory.EnumerateFiles 而不是 int[]string[].

下面有点难看,但您可以像这样使用空合并运算符 ??

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

或者创建一个扩展方法来做同样的事情(你可能想要一个比 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 });

Zip 对于空序列不是很有用,因为它会 return 空序列(它 return 序列基于较短的长度)。您也可以检查一下:

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

根据您可能的使用情况,我看不出 Zip'ing 目录和文件有何用处(忽略痛苦的 "Access denied" 和其他 IO 异常)。可能您想要一个文件列表以及父目录。下面的近似代码(获取每个目录的所有文件,将每个文件与目录信息配对,展平):

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