2011-01-24 10 views
14

que tienen una función con una expresión lambda algo como:funciones de depuración # C que contienen Expresiones Lambda

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

P. S. Estoy seguro de que hay una versión más agradable/más nítida/más idiomática de la afirmación anterior, podría ser bueno saber lo que podría ser, ¡aunque no es importante para la pregunta!

Si modifico cualquier otra cosa dentro de la función, mientras que la depuración decir una expresión Console.Write, los estados del depurador:

Modificación de un 'método' que contiene una expresión lambda evitará que la sesión de depuración continúe mientras Editar y continuar está habilitado.

Me preguntaba por qué este podría ser el caso?

Hubiera pensado que la IL generada para la función lamba y la declaración Console.Write serían separadas y que el depurador podría modificarlas y modificarlas cuando sea necesario. ¿Hay algún concepto fundamental que me falta respecto de la funcionalidad lamda?

Respuesta

11

No es que sea imposible para lograr en todos los casos (no creo). Sin embargo, sería una característica monstruosa para desarrollar.

Cuando se tiene la sintaxis de LINQ en su método, en general, que implica algún método anónimo ya sea detrás de las escenas:

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

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

... o simplemente de plano frente a las escenas (como en el ejemplo):

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

un método anónimo a su vez se compila en un tipo con los métodos de instancia para apoyar el código que has escrito.

En el ejemplo anterior, considere el f => f.Occurrences lambda. Esto se compila en un tipo con un campo de instancia único cuyo tipo es el del f local en esa lambda; este tipo contiene un método que devuelve f.Occurrences.

Así que cuando el código en última instancia, enumera sobre el resultado de la consulta LINQ, lo que pasa es que una instancia de este tipo generado por el compilador se está construyendo para cada field en data y un método único de este tipo que se ha generado para apoyar la f => f.Occurrences se llama a la expresión lambda para calcular Max.

El problema con edit-and-continue es que si hay cualquier cambio a las expresiones lambda en el método que se está editando, esto necesita cambiar los tipos generados, lo cual no es una opción. Uno podría pensar que esto aún se puede hacer en el caso en que no se altere nada sobre las expresiones lambda; siempre que se capturen los mismos locals y los métodos anónimos no se modifiquen, debería ser factible modificar un método con estas características mientras se depura igual que para los métodos "normales" en VS.

Pero como se puede ver, la generación tipo que se utiliza para apoyar los métodos anónimos en general y, por tanto, las consultas LINQ añade específicamente una gran cantidad de complejidad al proceso de edición y continuación, y en muchos casos hace que sea imposible (ya que requiere cambiar los tipos generados por completo).

Creo que simplemente se decidió que no valía la pena el costo de desarrollo ni siquiera se molestó en tratar de admitir este comportamiento en los escenarios limitados donde podría funcionar hipotéticamente.

-3

Hay una manera muy simple de depurar una expresión lamba. Convierta a un método anónimo utilizando un delegado en línea. Sencillo. :)

+8

Si esto es tan simple que debe dar el ejemplo de código;) recuerde, no es sencilla para todos. – ForceMagic

+0

Estoy de acuerdo con ForceMagic – Mastro

+0

No se puede usar el anónimo en lugar de immed: "_availableTypeCache.FirstOrDefault (delegate (Type t) {return t;}) La expresión no puede contener métodos anónimos" Debe pasar a LINQ con una var que está fuera del alcance de la llamada LINQ. –