2012-12-19 9 views
7

Wiele zwyczaj przeliczalny rozszerzeń mogą być realizowane w warunkach innych wbudowanych operacji - na przykład ten banalny sposób Wygoda:Wykorzystując PLINQ z niestandardowymi przeliczalny Rozszerzenia

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

Teraz będzie to żadnego zapytania PLINQ powrotem do sekwencyjnego działania chociaż PLINQ posiada również Dowolne - i jest równoznaczne z zaledwie tylko zmianą podpisu:

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

Ale powielenie go tak wydaje mi się bałagan.

Na początku pomyślałem, że coś, co poniżej, może działać, ale oczywiście nie, ponieważ metody rozszerzeń są metodami statycznymi, dlatego decyzja o wywołaniu Enumerable.Any w przeciwieństwie do ParallelQuery.Any została podjęta w czasie kompilacji na podstawie podpisu.

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

Doszedłem do wniosku, że to niemożliwe bez tworzenia kopii każdej metody z innym podpisem, ale być może jest coś, co przeoczyłem. (Gee zawsze z niemożliwych pytań!)


Być może lepszym przykładem pomocnika, który mógłby wykorzystać parallelization (może być oczywiście łańcuchy, itp) jest coś takiego.

public static IEnumerable<string> ToStrings(this IEnumerable<object> ienum) 
{ 
    return ienum.Select(a=> a.ToString()); 
} 

błąd^Compiler:

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>' 

również warte rozważenia jest to, że nie wszystkie ParallelQuery/przeliczalny metody są równoważne, nawet jeżeli się skompilować.

+0

jaki jest rzeczywisty pytanie? – jessehouwing

+1

Umm, err. Trochę porwał: "Czy istnieje sposób na napisanie rozszerzenia LINQ, które również działa z PLINQ?". – Fowl

+0

Czy wszystkie metody rozszerzenia są tak krótkie? Ile ich masz? – svick

Odpowiedz

1

Zrobiłem podobne do pisania rozszerzeń IQueryable/IEnumerable. Próba wyodrębnienia typowych bitów związanych z deklarowaniem zmiennej statycznej zawierającej wyrażenie, a następnie odwoływanie się do tego wyrażenia z dwóch różnych wersji funkcji. Nie mam już kodu, a kiedy skończyłem, był bardzo brzydki i nie byłem z niego zadowolony. Oto prosty przykład.

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

Ostatecznie poziom usuwania duplikatów nie był w ogóle dobry i byłby bardziej skomplikowany przez parametry ogólne. Może jednak da ci to pomysł.

Czekamy na kolejne pomysły.

1

Można to zrobić za pomocą sprawdzone metody odlewania wewnątrz (tj wykonawcze przełączania) tak:

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)); 
} 
+0

Jak to pomaga? Nadal oznacza, że ​​masz dwa razy ten sam kod. – svick

+0

@svick ala 'Doszedłem do wniosku, że to niemożliwe bez tworzenia kopii każdej metody z innym podpisem, ale być może jest coś, czego mi brakowało' & "Czy istnieje sposób napisania rozszerzenia LINQ, które działa również z PLINQ?"" jego rzeczywistym pytaniem nie jest pisanie tego dwa razy, ale posiadanie pojedynczego podpisu, który będzie sprytny w zależności od zachowania wyliczeniowego, dla którego jest to rozwiązanie – user1793607

+2

Ale uważam, że podstawową przyczyną tego jest uniknięcie powielania kodu. – svick

Powiązane problemy