2011-01-24 14 views
14

Ho una funzione con un qualcosa di simile espressione lambda:C# funzioni di debug che contengono lambda espressioni

int maxOccurrences = (from field in data select field).Max(f => f.Occurrences) 

P.S. Sono sicuro che c'è una versione più bella/più normale/più idiomatica della dichiarazione precedente, potrebbe essere bello sapere cosa potrebbe essere, anche se non è importante per la domanda!

Se modifico qualsiasi altra cosa all'interno della funzione, mentre il debug dicono un'espressione Console.Write, gli stati del debugger:

modifica di un 'metodo' che contiene un'espressione lambda impedirà la sessione di debug di continuare mentre Modifica e continuazione è abilitato.

Mi chiedevo perché questo potrebbe essere il caso?

Avrei pensato che l'IL generato per la funzione lamba e l'istruzione Console.Write sarebbero separati e che il Debugger potrebbe modificare e modificare se necessario. C'è qualche concetto fondamentale che mi manca riguardo alla funzionalità lamda?

risposta

11

Non è che sarebbe impossibile da raggiungere in tutti i casi (non credo). Tuttavia, sarebbe una caratteristica mostruosa da sviluppare.

Quando hai la sintassi LINQ nel metodo, in generale, che comporta un certo metodo anonimo sia dietro le quinte:

// This LINQ query... 
var fields = from field in data select field; 

// ...is equivalent to this: 
var fields = data.Select(f => f); 

... o solo flat-out davanti le quinte (come nel tuo esempio):

(from field in data select field).Max(f => f.Occurrences) // <- lambda 

un metodo anonimo a sua volta viene compilato in un tipo con metodi di istanza per sostenere il codice che hai scritto.

Nell'esempio sopra, considerare il lambda f => f.Occurrences. Questo viene compilato in un tipo con un campo di istanza singolo il cui tipo è quello del locale f in quella lambda; questo tipo contiene un metodo che restituisce f.Occurrences.

Così, quando il codice in ultima analisi, enumera sopra il risultato della query LINQ, quello che sta succedendo è che un esempio di questo tipo generato dal compilatore è in fase di costruzione per ogni field in data e unico metodo di quel tipo che è stato generato per sostenere il f => f.Occurrences l'espressione lambda viene chiamata per calcolare Max.

Il problema con modifica-e-continua è che se c'è qualsiasi modifica alle espressioni lambda nel metodo che si modifica, ciò richiede la modifica dei tipi generati, che non è un'opzione. Si potrebbe pensare che questo potrebbe ancora essere fatto nel caso in cui nulla è alterato circa le espressioni lambda stesse; finché gli stessi locatori vengono catturati e i metodi anonimi sono invariati, dovrebbe essere possibile modificare un metodo con queste caratteristiche durante il debug proprio come avviene per i metodi "normali" in VS.

Ma, come si può vedere, la generazione tipo usato per sostenere i metodi anonimi, in generale, e quindi le query LINQ aggiunge in modo specifico una grande quantità di complessità al processo di modifica-and-continue, e in molti casi rende impossibile (poiché richiede di cambiare completamente i tipi generati).

Penso che sia stato appena deciso che non valeva il costo di sviluppo nemmeno preoccuparsi di provare a supportare questo comportamento negli scenari limitati in cui potrebbe ipoteticamente funzionare.

-3

Esiste un modo molto semplice per eseguire il debug di un'espressione di lamba. Convertirlo in un metodo anonimo usando un delegato in linea. Semplice.

+8

Se è così semplice è necessario fornire l'esempio di codice;) ricordate, non è semplice per tutti. – ForceMagic

+0

Concordo con ForceMagic – Mastro

+0

Non è possibile utilizzare anonimo sul posto da immed: "_availableTypeCache.FirstOrDefault (delegato (tipo t) {return t;}) L'espressione non può contenere metodi anonimi" Devi passare a LINQ con una variabile che è al di fuori dell'ambito della chiamata LINQ. –