2011-10-07 43 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

相关问题