2012-12-19 8 views
7

Molte estensioni enumerabili personalizzato può essere implementato in termini di altre operazioni built - per esempio questo metodo comodo banale:Sfruttando PLINQ con personalizzati enumerabili estensioni

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

Ora, questo costringerà qualsiasi richiesta PLINQ torna a funzionamento sequenziale anche se PLINQ ha anche un Qualsiasi - ed è equivalente con appena solo un cambiamento di firma:

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

Ma duplicando in questo modo sembra disordinato a me.

In un primo momento ho pensato qualcosa di simile al di sotto potrebbe funzionare, ma ovviamente non lo fa^perché i metodi di estensione sono metodi statici e quindi la decisione di chiamare Enumerable.Any al contrario di ParallelQuery.Any è fatta al momento della compilazione sulla base di firma.

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

sono giunto alla conclusione che è impossibile senza la creazione di una copia di ogni metodo con una firma diversa, ma forse c'è qualcosa che ho perso. (Gee sempre con le domande impossibili!)


Forse un esempio migliore di un aiutante che potrebbero trarre beneficio dalla parallelizzazione (può ovviamente essere incatenato, ecc) è qualcosa di simile.

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

errore^del compilatore:

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

Anche la pena prendere in considerazione è che non tutto il ParallelQuery/metodi enumerabili sono equivalenti, anche se la compilazione.

+0

qual è la domanda reale? – jessehouwing

+1

Umm, err. un po 'portato via: "C'è un modo per scrivere un'estensione LINQ che funzioni anche con PLINQ?". – Fowl

+0

Tutti i tuoi metodi di estensione sono così brevi? Quanti ne hai? – svick

risposta

1

Ho fatto simile per scrivere estensioni IQueryable/IEnumerable. Cercando di calcolare i bit comuni coinvolti dichiarando una variabile statica contenente un'espressione, quindi facendo riferimento a tale espressione dalle due diverse versioni della funzione. Non ho più il codice, e quando ho finito era molto brutto e non ero soddisfatto. Ecco un esempio banale.

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

In definitiva il livello di deduplicazione non era affatto buono e sarebbe reso più complicato da parametri generici. Forse questo ti darà un'idea comunque.

In attesa di vedere altre idee.

1

Si potrebbe farlo utilizzando checked scacciando all'interno del metodo (cioè runtime switching) in questo modo:

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

Come può essere d'aiuto? È ancora significa che hai lo stesso codice due volte. – svick

+0

@svick ala 'Sono arrivato alla conclusione impossibile senza creare una copia di ogni metodo con una firma diversa, ma forse c'è qualcosa che mi è sfuggito. &' "C'è un modo per scrivere un'estensione LINQ che funzioni anche con PLINQ?"La sua vera domanda non è scrivere due volte ma avere una singola firma che sarà intelligente a seconda del comportamento di enumerazione, per cui questa è una soluzione – user1793607

+2

Ma credo che il motivo alla base di ciò sia evitare la duplicazione del codice. – svick

Problemi correlati