简化LINQ查询

时间:2011-09-06 20:43:37

标签: linq

我需要一点帮助来简化LINQ查询。条件如下:

  • 我需要将bool IsValid(string expression)应用于给定序列的每个元素。
  • 如果IsValid对所有元素都为真,请返回true
  • 如果任何元素的IsValid为false,请返回false
  • 如果序列为空或空,则还返回false

我提出的查询是

try
{
    (sequence.DefaultIfEmpty().Where(item => !IsValid(item).Count() == 0)
}
catch (ArgumentNullException)
{
    return false;
}

重点是IsValid(null)会抛出ArgumentNullException阻止的catch。但是,我认为这太棘手了。有什么方法可以简化方法而不依赖于这个事实吗?

3 个答案:

答案 0 :(得分:6)

为什么不:

return sequence.Any() && sequence.All(item => IsValid(item));

如果您担心导致Resharper警告的单独sequence.Any()检查(由任何序列保证,您只能像网络,数据库等那样迭代一次),您可以编写一个通用扩展名执行检查并仅迭代序列一次的方法:

public static bool NotEmptyAndValid<T>(this IEnumerable<T> source, 
                                       Func<T, bool> predicate)
{
    bool hasItem = false;
    foreach(var item in source)
    {
        hasItem = true;
        if(!predicate(item))
            return false;
    }
    return hasItem;
}

然后你可以这样做:

return sequence.NotEmptyAndValid( x => IsValid(x));

答案 1 :(得分:3)

你应该可以使用:

return sequence.Any() && sequence.All(item => IsValid(item));

答案 2 :(得分:1)

我不确定只需一次通过即可轻松完成很好。我确定它是可行的,但我不确定它会不会很好。但是,编写自己的扩展方法很容易:

(编辑:我看到BrokenGlass现在用foreach编写了一个类似的方法。我将把它作为替代方法。)

public static boolean AllAndNotEmpty<T>(this IEnumerable<T> source,
                                        Func<T, bool> predicate)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    if (predicate == null)
    {
        throw new ArgumentNullException("predicate");
    }
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            return false;
        }
        do
        {
            if (!predicate(iterator.Current))
            {
                return false;
            }
        } while (iterator.MoveNext());            
    }
    return true;
}

然后:

var result = items.AllAndNotEmpty(IsValid);