foreach in list o foreach in list.where [duplicate]

0

Non so come chiamare questa domanda.

Questo è il mio esempio:

foreach (var item in lstItem.Where(item => stock.ItemCode == item.ItemCode))
{
     stock.ItemName = item.ItemName;
     stock.ItemUnitName = item.ItemUnitName;
     stock.BrandName = item.BrandName;
     stock.FamilyName = item.FamilyName;
}

o

// Assume list has items
var list = lstItem.Where(item => stock.ItemCode == item.ItemCode);
foreach (var item in list)
{
     stock.ItemName = item.ItemName;
     stock.ItemUnitName = item.ItemUnitName;
     stock.BrandName = item.BrandName;
     stock.FamilyName = item.FamilyName;
}

Quale è meglio?

    
posta Steve Lam 08.05.2014 - 06:26
fonte

2 risposte

0

Ci sono due domande interessanti racchiuse in una qui.

In primo luogo, è meglio suddividere espressioni più complesse in più semplici e forse cogliere l'opportunità di dare le variabili ai nomi utili?

Questa è spesso una buona idea, ma in questo caso il codice potrebbe essere meglio letto come:

var wanted_items = lstItem.Where(item => stock.ItemCode == item.ItemCode);
foreach (var item in wanted_items)

In secondo luogo, ci sono problemi di prestazioni nella rottura di espressioni come questa?

Non è così facile rispondere, nel caso generale. Nella maggior parte dei linguaggi, un costrutto di questo tipo porterebbe a tutti gli elementi dell'elenco in elaborazione per filtrare quelli richiesti, quindi i singoli elementi elaborati di nuovo per applicare l'assegnazione. Se c'è una sola corrispondenza, la prima passerà (in media) a esaminare il doppio degli elementi necessari.

Ma questo è C # e Linq, quindi ora l'elenco sarà un iteratore o sarà tradotto in SQL, entrambi i quali ottimizzano l'elaborazione, in misura maggiore o minore. In questo caso particolare la performance sarà (dovrebbe essere) esattamente la stessa sia che l'espressione sia divisa o meno, ma ci sono costrutti strettamente correlati in cui la divisione dell'espressione come questa può cristallizzare un particolare percorso per l'esecuzione e avere un impatto prestazionale piuttosto grave.

In definitiva, dovresti sempre scrivere il codice più leggibile possibile usando i migliori algoritmi possibili e il miglior uso possibile delle librerie di base sottostanti. Se si hanno preoccupazioni per le prestazioni, è necessario valutare e misurare prima ancora di pensare di modificare il codice.

    
risposta data 08.05.2014 - 07:15
fonte
1

Entrambi i tuoi esempi sono funzionalmente equivalenti.

La ragione di ciò è che un'enumerazione non viene valutata finché non è assolutamente necessaria. Guardando il tuo secondo esempio:

var list = lstItem.Where(item => stock.ItemCode == item.ItemCode);
foreach (var item in list)
{
 stock.ItemName = item.ItemName;
 stock.ItemUnitName = item.ItemUnitName;
 stock.BrandName = item.BrandName;
 stock.FamilyName = item.FamilyName;
}

Quello che succede è che list non è una lista. Piuttosto è un enumeratore di lstItem con la condizione Where su di esso. Questo enumeratore viene valutato una volta per ogni iterazione del ciclo foreach.

La ragione di ciò è che questo consentirà il massimo delle prestazioni se il ciclo foreach viene chiuso in anticipo. L'enumeratore potrebbe dover eseguire alcuni calcoli complessi quando viene eseguito e quindi il cortocircuito può, in alcuni casi, comportare un codice molto più rapido.

È meglio non pensare a var list = lstItem.Where(item => stock.ItemCode == item.ItemCode); come a darti una lista. Piuttosto, ti dà un oggetto che restituirà l'oggetto successivo quando viene richiesto fino a quando non esaurisce gli elementi. Teoricamente potrebbe andare avanti all'infinito ed è del tutto possibile scrivere un enumeratore che gira su se stesso.

Personalmente, preferisco il tuo primo snippet di codice in quanto richiede meno letture. Nota che quando il compilatore ottimizza il tuo codice, la variabile temporanea list verrà ottimizzata a meno che non venga utilizzata in seguito.

    
risposta data 08.05.2014 - 08:01
fonte

Leggi altre domande sui tag