7

多くのカスタム Enumerable 拡張機能は、他の組み込み操作の観点から実装できます。たとえば、次の簡単な便利なメソッドです。

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

これで、PLINQ にも Any - が含まれていても、すべての PLINQ クエリが強制的に順次操作に戻され、署名を変更するだけで同等になります。

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

しかし、このように複製するのは面倒です。

最初は、次のようなものが機能する可能性があると考えていましたが、もちろん機能しません^拡張メソッドは静的メソッドであり、呼び出しの決定Enumerable.AnyParallelQuery.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));
}

各メソッドのコピーを異なる署名で作成しないと不可能だという結論に達しましたが、見逃しているものがあるかもしれません。(いつも不可能な質問をしてください!)


おそらく、並列化の恩恵を受けるヘルパーのより良い例は、このようなものです。

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 メソッドは、たとえコンパイルされたとしても、すべてが同等であるとは限らないことも考慮する価値があります。

4

2 に答える 2

1

I have done similar for writing IQueryable/IEnumerable extensions. Trying to factor out the common bits involved declaring static variable holding an Expression, and then referencing that expression from the two different versions of the function. I don't have the code anymore, and when I was done, it was very ugly and I wasn't satisfied with it. Here is a trivial example.

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);

Ultimately the level of de-duplication was not good at all, and would be made more complicated by generic parameters. Maybe this will give you an idea though.

Looking forward to seeing others ideas.

于 2012-12-19T02:53:51.480 に答える
1

次のように、メソッド内でチェック済みのキャスト (つまり、ランタイムの切り替え) を使用することで、これを行うことができます。

public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items)
{
    var parallelItems = items as ParallelQuery<TElement>
    if(parallelItems != null)
    {
         return parallelItems.Any(a => EqualityComparer<TElement>.Default.Equals(a, item))
    }
    //other runtime checks
    ....
    //else return default IEnumerable implementation
    return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item));
}
于 2012-12-19T14:54:19.037 に答える