У меня есть небольшой метод расширения служебной программы, который выполняет некоторые нулевые проверки некоторых методов расширения LINQ в IEnumerable<T>
. Код выглядит так
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
напрямую, а не заключать его в лямбду?
Редактировать
Поскольку на самом деле кратко передать метод расширения Enumerable
, я удалил NullableIntersect
(и другие) методы и просто вызвал обнуляемую оболочку напрямую.
Кроме того, как указывает Энтони, семантика того, что должен делать перечисляемый Empty, отличается в зависимости от метода расширения, то есть Union
против Intersect
. Поэтому я переименую метод 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);