2011-09-06 85 views
2

我需要一些簡化LINQ查詢的幫助。條件如下:簡化LINQ查詢

  • 我需要將bool IsValid(string expression)應用於給定序列的每個元素。
  • 如果IsValid對所有元素均爲true,則返回true
  • 如果IsValid對於任何元素均爲false,則返回false
  • 如果序列爲空或空,也返回false

我想出了查詢

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

的一點是,IsValid(null)拋出一個ArgumentNullException這是由catch塊捕獲。但是,我認爲這太棘手。沒有任何方法可以簡化方法而不依賴於這個事實?

回答

6

爲什麼不:

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

如果你擔心單獨sequence.Any()檢查,結果在一個ReSharper的警告(這是必要的與你只能遍歷一次像一個網絡,數據庫等任何序列)你可以寫,做檢查和迭代序列只有一次的通用擴展方法:

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)); 
+0

是的,你是對的!但是,這引發了ReSharper的「可能的IEnumerable多重枚舉」警告,我想避免這種警告。 – User

+0

DefaultIfEmpty將只返回一個空項目 - 這裏的目的是什麼? –

+0

是剛剛修復那部分,沒有看到空集合的要求 – BrokenGlass

3

您應該能夠使用:

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

是的,你是對的!但是,這引發了ReSharper的「可能的IEnumerable多重枚舉」警告,我想避免這種警告。 – User

+0

@用戶:在這種情況下,爲了讓您的空/空檢查正常,循環可能是最好的選擇... –

+0

看起來像一個同時回答給我。 –

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