【问题标题】:Can I get a Func object for an Extension method我可以为扩展方法获取 Func 对象吗
【发布时间】:2011-10-07 16:37:39
【问题描述】:

我有一个小型实用程序扩展方法,它对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&lt;T&gt;.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);

【问题讨论】:

    标签: linq extension-methods ienumerable


    【解决方案1】:

    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 的交集将导致空序列。最终,由你决定你想要的行为。

    【讨论】:

    • 我自己刚刚追踪到了这个。为速度+1。
    • @Lucas,我​​刚刚添加了一个问题,请务必检查修订版本,看看它是否是一个绊脚石。
    • 是的,我确实注意到了这一点,并在我的项目中将扩展方法重命名为IgnoreIfNull,以更好地反映语义,即var output = first.IgnoreIfNull(second, Enumerable.Intersect)
    猜你喜欢
    • 2011-07-30
    • 2011-11-21
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 2013-07-16
    • 2015-03-15
    相关资源
    最近更新 更多