2011-10-07 37 views
0

我有一個小的工具擴展方法,對IEnumerable<T>中的一些LINQ擴展方法執行一些空的檢查。該代碼看起來像這樣我可以得到擴展方法的Func對象

public static class MyIEnumerableExtensions 
{ 
    // Generic wrapper to allow graceful handling of null values 
    public static IEnumerable<T> NullableExtension<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<IEnumerable<T>, IEnumerable<T>, IEnumerable<T>> f) 
    { 
     if (first == null && second == null) return Enumerable.Empty<T>(); 
     if (first == null) return second; 
     if (second == null) return first; 
     return f(first, second); 
    } 

    // Wrap the Intersect extension method in our Nullable wrapper 
    public static IEnumerable<T> NullableIntersect<T>(this IEnumerable<T> first, IEnumerable<T> second) 
    { 
     // It'd be nice to write this as 
     // 
     // return first.NullableExtension<T>(second, IEnumerable<T>.Intersect); 
     // 
     return first.NullableExtension<T>(second, (a,b) => a.Intersect(b)); 
    } 
} 

那麼,有沒有辦法在IEnumerable<T>.Intersect擴展方法NullableExtension傳遞,而不是直接在一個lambda包裝呢?

編輯

因爲它實際上是簡潔在Enumerable擴展方法來傳遞,我除去NullableIntersect(和其他)的方法和只直接調用可爲空的包裝。另外,正如安東尼指出的那樣,根據擴展方法,空值枚舉應該做什麼的語義是不同的,即UnionIntersect。因此,我將NullableExtension方法重命名爲IgnoreIfNull,它更好地反映了通用行爲。

public static class MyIEnumerableExtensions 
{ 
    // Generic wrappers to allow graceful handling of null values 
    public static IEnumerable<T> IgnoreIfNull<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<IEnumerable<T>, IEnumerable<T>, IEnumerable<T>> f) 
    { 
     if (first == null && second == null) return Enumerable.Empty<T>(); 
     if (first == null) return second; 
     if (second == null) return first; 
     return f(first, second); 
    } 

    public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<IEnumerable<T>, IEnumerable<T>, IEnumerable<T>> f) 
    { 
     return f(first ?? Enumerable.Empty<T>(), second ?? Enumerable.Empty<T>()); 
    } 

} 

// Usage example. Returns { 1, 4 } because arguments to Union and Intersect are ignored 
var items = new List<int> { 1, 4 }; 
var output1 = items.IgnoreIfNull(null, Enumerable.Union).IgnoreIfNull(null, Enumerable.Intersect); 

// Usage example. Returns { } because arguments to Union and Intersect are set to empty 
var output2 = items.EmptyIfNull(null, Enumerable.Union).EmptyIfNull(null, Enumerable.Intersect); 

回答

2

Intersect被靜態類Enumerable中定義的。你可以將它傳遞到您的方法如下面

return first.NullableExtension<T>(second, Enumerable.Intersect); 

注:可能關心你的邏輯在一個空序列的情況下的行爲。例如,在

List<int> first = null; 
var second = new List<int> { 1, 4 }; 
var output = first.NullableIntersect(second).ToList(); 

的情況下已經定義它使得output包含{1, 4}(的second元件)。我可能會認爲first將被視爲空序列,並且與second的交點會導致空序列。最終,這是你決定你想要的行爲。

+0

我自己跟蹤了這一點。爲了速度而+1。 – Lucas

+0

@盧卡斯,我剛剛添加了一個問題,一定要檢查修訂版,看它是否是一個絆腳石。 –

+0

是的,我注意到了這一點,並在我的項目中將擴展方法重命名爲'IgnoreIfNull',以更好地反映語義,即'var output = first.IgnoreIfNull(second,Enumerable.Intersect)' – Lucas

相關問題