【问题标题】:LINQ to return null if an array is empty如果数组为空,LINQ 将返回 null
【发布时间】:2015-02-19 16:07:10
【问题描述】:
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 的情况下有什么方法可以做到这一点?

编辑:主要问题是如何在不存储中间结果的情况下执行此操作。类似于NULLIF() 来自T-SQL 的东西,如果条件为假,您将返回您传入的内容,如果条件为真,则返回NULL

【问题讨论】:

    标签: c# linq linq-to-objects


    【解决方案1】:

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

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

    【讨论】:

    • 我非常喜欢这种方法。如果您想要空安全,您还可以添加对 seq == null 的检查,这与我之前的解决方案不同。
    • @Sinatr 这有什么好处?它使呼叫者在呼叫站点使用ToArray()
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      没有办法让Select 返回null,但如果您不想创建额外的数组,您可以这样做:

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

      【讨论】:

      • 为什么将结果迭代两次,而不是 OP 当前的结果?
      • Any() 将立即返回,因为投影为空或至少有一个元素,因此它不会枚举整个集合两次。
      猜你喜欢
      • 1970-01-01
      • 2011-06-22
      • 2013-11-11
      • 2019-07-17
      • 1970-01-01
      • 2013-11-26
      • 2021-09-15
      • 2021-04-29
      • 1970-01-01
      相关资源
      最近更新 更多