我可以为Extension方法获取Func对象

时间:2011-10-07 16:37:39

标签: linq extension-methods ienumerable

我有一个小的实用程序扩展方法,它对IEnumerable<T>中的某些LINQ扩展方法执行一些空值检查。代码看起来像这样

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(和其他)方法,并直接调用可空包装器。

另外,正如Anthony指出的那样,Empty枚举应该做的语义因扩展方法而异,即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);

1 个答案:

答案 0 :(得分: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的交集将导致空序列。最终,这是你决定你想要的行为。