Many custom Enumerable extensions can be implemented in terms of other builtin operations - for example this trivial convenience method:
public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items)
{
return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
Now this will force any PLINQ query back to sequential operation even though PLINQ also has a Any - and is equivalent with just just a signature change:
public static bool AnyOf<T>(this T item, ParallelQuery<T> items)
{
return items.Any(a => EqualityComparer<T>.Default.Equals(a, item));
}
But duplicating it like this seems messy to me.
At first I thought something like the below might work, but of course it does not^ because extension methods are static methods and therefore the decision to call Enumerable.Any
as opposed to ParallelQuery.Any
is made at compile time based on signature.
public static bool AnyOf<TElement, TEnumerable>(this TElement item, TEnumerable items)
where TEnumerable : class, IEnumerable<TElement>
{
return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
I've come to the conclusion it's impossible without creating a copy of each method with a different signature, but maybe there's something I've missed. (Gee always with the impossible questions!)
Perhaps a better example of a helper that would benefit from parallelization (can obviously be chained, etc. ) is something like this.
public static IEnumerable<string> ToStrings(this IEnumerable<object> ienum)
{
return ienum.Select(a=> a.ToString());
}
^ Compiler error:
The type 'ParallelQuery<TElement>' cannot be used as type parameter
'TEnumerable' in the generic type or method
'AnyOf<TElement,TEnumerable>(TElement, TEnumerable)'. There is no
implicit reference conversion from 'ParallelQuery<TElement>' to
'IEnumerable<TElement>'
Also worth considering is that not all of the ParallelQuery/Enumerable methods are equivalent, even if they do compile.