可以使用其他内置操作来实现许多自定义的Enumerable扩展-例如,这种简单的便捷方法:

public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items)
{
    return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}

现在,这将迫使任何PLINQ查询返回顺序操作,即使PLINQ也具有Any-且仅签名更改就等效:
public static bool AnyOf<T>(this T item, ParallelQuery<T> items)
{
    return items.Any(a => EqualityComparer<T>.Default.Equals(a, item));
}

但是像这样复制它对我来说似乎很困惑。

起初,我认为类似以下内容的方法可能会起作用,但是当然不行,因为扩展方法是静态方法,因此在编译时基于签名决定调用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));
}

我得出的结论是,如果不为每个方法创建具有不同签名的副本,那是不可能的,但是也许我错过了一些东西。 (Gee总是带着不可能的问题!)

也许可以从并行化(显然可以链接等)中受益的一个更好的 helper 例子是这样的。
public static IEnumerable<string> ToStrings(this IEnumerable<object> ienum)
{
    return ienum.Select(a=> a.ToString());
}

^编译器错误:
 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>'

还值得考虑的是,即使所有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);

最终,重复数据删除的水平根本不好,并且将因通用参数而变得更加复杂。也许这会给您一个想法。

期待看到别人的想法。

关于c# - 通过自定义Enumerable Extensions利用PLINQ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13944473/

10-11 19:08