2010-02-15 60 views
3

我想創建一個擴展「WhereNot」WhereNot LINQ表達

所以我可以使用:

Dim x = "Hello world " 
Dim y = x.Split.WhereNot(AddressOf String.IsNullOrEmpty) 

注意,我在這裏的目的是學習LINQ表達式;沒有解決我的問題。

我craated這個功能:

<Extension()> _ 
Public Function WhereNot(Of TElement)(ByVal source As IQueryable(Of TElement), ByVal selector As Expression(Of Func(Of TElement, Boolean))) As IQueryable(Of TElement) 
    Return source.Where(GetWhereNotExpression(selector)) 
End Function 

我不知道如何切換布爾標誌,將函數求反做呢?

答案在兩個vb.net和C#都welcommed

回答

10

我意識到這是一個非常古老的回答問題,但我認爲所選答案是誤導性的,因爲提問者正在尋找一個表達式,並且所選答案提供了一個lambda。

這意味着它從IQueryable的調用將返回IEnumerable<T>而不是IQueryable<T>。這迫使表達式進行編譯,並可能導致對Linq提供程序的訪問不甚優化。

這是直接解決原始問題的答案。

public static class NegationExpressionHelper 
{ 
    public static IQueryable<T> WhereNot<T>(this IQueryable<T> queryable, Expression<Func<T,bool>> predicate) 
    { 
     return queryable.Where(predicate.Invert()); 
    } 
    public static Expression<Func<T, bool>> Invert<T>(this Expression<Func<T, bool>> original) 
    { 
     return Expression.Lambda<Func<T, bool>>(Expression.Not(original.Body), original.Parameters.Single()); 
    } 
} 
1

是這樣的求反方法將幫助您:

Public Function Negate(Of T)(ByVal predicate As Func(Of T, Boolean)) As Func(Of T, Boolean) 
    Return Function(x) Not predicate(x) 
End Function 

,然後用它是這樣的:

Dim x = "Hello world " 
Dim y = x.Split.Where(Negate(Of String)(AddressOf String.IsNullOrEmpty)) 

或者使用如下的WhereNot()方法:

<Extension> _ 
Public Shared Function WhereNot(Of T)(ByVal source As IEnumerable(Of T), ByVal predicate As Func(Of T, Boolean)) As IEnumerable(Of T) 
    Return source.Where(Negate(predicate)) 
End Function