许多自定义Enumerable扩展可以根据其他内置操作实现 - 例如这个简单的方便方法:
public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items)
{
return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
Run Code Online (Sandbox Code Playgroud)
现在这将强制任何PLINQ查询回到顺序操作,即使PLINQ也有一个Any - 并且只相当于一个签名更改:
public static bool AnyOf<T>(this T item, ParallelQuery<T> items)
{
return items.Any(a => EqualityComparer<T>.Default.Equals(a, item));
}
Run Code Online (Sandbox Code Playgroud)
但是像这样复制它对我来说似乎很麻烦.
起初我认为类似下面的东西可能会起作用,但当然它不会^因为扩展方法是静态方法,因此决定调用Enumerable.Any
而不是ParallelQuery.Any
基于签名在编译时进行.
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));
}
Run Code Online (Sandbox Code Playgroud)
我得出的结论是,如果没有使用不同的签名创建每个方法的副本,那是不可能的,但也许我错过了一些东西.(啧啧总是带着不可能的问题!)
或许可以从并行化(显然可以链接等)中受益的帮助器的更好示例是这样的.
public static IEnumerable<string> ToStrings(this IEnumerable<object> ienum)
{
return ienum.Select(a=> a.ToString());
}
Run Code Online (Sandbox Code Playgroud)
^编译器错误:
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>'
Run Code Online (Sandbox Code Playgroud)
另外值得考虑的是,并非所有的ParallelQuery/Enumerable方法都是等效的,即使它们编译也是如此.
我在编写 IQueryable/IEnumerable 扩展时做了类似的事情。尝试分解出公共位涉及声明包含表达式的静态变量,然后从函数的两个不同版本引用该表达式。我不再有代码了,当我完成后,它非常丑陋,我对此并不满意。这是一个简单的例子。
Expression<Func<PersonHistory, bool>> IsCurrent = (p) => p.Ends > DateTime.Now && p.Starts <= DateTime.Now;
//Then in each Extension method:
var query = db.PersonHistories.Where(IsCurrent);
Run Code Online (Sandbox Code Playgroud)
最终,重复数据删除的水平根本不好,并且会因通用参数而变得更加复杂。也许这会给你一个想法。
期待看到其他人的想法。