如果数组为空,LINQ to return null

LINQ to return null if an array is empty

public class Stuff
{
  public int x;
  // ... other stuff
}

我有一个 IEnumerable<Stuff>,我想为集合中所有 Stuff 对象的所有 x 属性构建一个 int[]

我愿意:

IEnumerable<Stuff> coll;
// ...
var data = coll.Select(s => s.x).ToArray();

如果集合为空,我想要的是空数组而不是 int[0]。也就是说,如果!coll.Any(),那么我要data = null。 (我的实际需求是coll是一个复杂的LINQ表达式的中间结果,我想用LINQ对表达式链进行操作,而不是保存中间结果)

我知道 int[0] 在许多情况下比 null 更可取,但我存储了许多这样的结果,并且我更愿意传递 nulls 而不是空数组。

所以我目前的解决方案是这样的:

var tmp = coll.Select(s => s.x).ToArray();
int[] data = tmp.Any() ? tmp : null;

有什么方法可以不存储 tmp

编辑:主要问题是如何在不存储中间结果的情况下做到这一点。类似于 T-SQL 中的 NULLIF(),如果条件为假,则返回传入的内容;如果条件为真,则返回 NULL

仅当 coll 不为空时才创建数组,反之亦然:

int[] data = null;
if(coll.Any()) data = coll.Select(s => s.x).ToArray();

没有办法让 Select 变为 return null,但如果您不想创建额外的 array,您可以这样做:

var tmp = coll.Select(s => s.x);
int[] data = tmp.Any() ? tmp.ToArray() : null;

如果你经常这样做,你可以写一个扩展方法:

public static class IEnumerableExt
{
    public static T[] ToArrayOrNull<T>(this IEnumerable<T> seq)
    {
        var result = seq.ToArray();

        if (result.Length == 0)
            return null;

        return result;
    }
}

那么您的调用代码将是:

var data = coll.Select(s => s.x).ToArrayOrNull();