2009-02-24 15 views
11

Por lo tanto, cada vez que escribo una expresión lambda o método anónimo dentro de un método que no obtuve bastante bien, me veo obligado a recompilar y reiniciar toda la aplicación o marco de prueba de la unidad para solucionarlo. Esto es realmente molesto, y termino perdiendo más tiempo de lo que ahorré usando estas construcciones en primer lugar. Es tan malo que intento alejarme de ellos si puedo, a pesar de que Linq y lambdas se encuentran entre mis características favoritas de C#.¿Por qué no puedo editar un método que contiene un método anónimo en el depurador?

Supongo que hay una buena razón técnica de por qué es así, y tal vez alguien lo sepa? Además, ¿alguien sabe si se solucionará en VS2010?

Gracias.

Respuesta

14

Sí, hay una muy buena razón por la que no puede hacer esto. La simple razón es el costo. El costo de habilitar esta función en C# (o VB) es extremadamente alto.

Editar una función lambda es un caso específico de una clase de problemas ENC que son muy difíciles de resolver con la arquitectura ENC (Edit'n'Continue) actual. Es decir, es muy difícil de ENC cualquier método que en la ENC realiza una de las siguientes: -

  1. Genera metadatos en forma de una clase
  2. Edita o genera un método genérico

El El primer problema es más una restricción lógica, pero también se topa con un par de limitaciones en la arquitectura ENC. A saber, el problema es generar la primera clase no es terriblemente difícil. Lo molesto es generar la clase después de la segunda edición. El motor ENC debe comenzar a rastrear la tabla de símbolos no solo para el código activo, sino también para las clases generadas. Normalmente, esto no es tan malo, pero esto se vuelve cada vez más difícil cuando la forma de una clase generada se basa en el contexto en el que se utiliza (como es el caso de lambdas debido a cierres). Más importante aún, ¿cómo se resuelven las diferencias frente a las instancias de las clases que ya están activas en el proceso?

El segundo problema es una limitación estricta en la arquitectura CLR ENC. No hay nada que C# (o VB) pueda hacer para evitar esto.

Lambdas desafortunadamente golpeó estas dos cuestiones sin éxito. La versión corta es que ENC'ing a lambda implica muchas mutaciones en las clases existentes (que pueden o no haberse generado a partir de otras ENCs). El gran problema consiste en resolver las diferencias entre el nuevo código y las instancias de cierre existentes en el espacio de proceso actual. Además, las lambdas tienden a usar genéricos mucho más que otros códigos y llegan al problema n. ° 2.

Los detalles son bastante peludos y demasiado complicados para una respuesta SO normal. He considerado escribir una larga publicación en el blog sobre el tema. Si lo hago, lo vincularé nuevamente a esta respuesta en particular.

+1

Directo de la boca del caballo. +1 –

+0

@Jon Hemos tenido muchas reuniones internas sobre este tema y he tenido que dar esta presentación muchas veces. Realmente necesito escribir un doc completo sobre el tema. Blogging parece ser un buen lugar para eso. Existe la esperanza de que esto se resuelva en una versión futura de VS. – JaredPar

+1

Por favor, escriba un blog al respecto. – Eyvind

0

Reiniciar una prueba unitaria debería tomar una cuestión de segundos, si eso. Nunca me ha gustado el modelo de "editar y continuar" para ser honesto: siempre debes volver a ejecutar desde cero IMO, en caso de que el cambio a mitad de la ejecución haya afectado al código que se ejecutó anteriormente. Dado que, es mejor utilizar pruebas unitarias que se pueden ejecutar con un cambio muy rápido. Si las pruebas de su unidad individual toman un tiempo insoportable para comenzar, eso es algo que debe considerar abordar.

EDITAR: En cuanto a por qué no funciona, puede encontrar que funciona para algunas lambdas pero no para otras. Las expresiones Lambda que no capturan ninguna variable (incluido this) se almacenan en caché en una variable privada estática, por lo que solo se crea una instancia del delegado. Cambiar el código significa reiniciar esa variable que podría tener interesantes efectos secundarios, sospecho.

+0

Estoy de acuerdo ..., pero no es una respuesta a la pregunta. –

+0

Sabía que usted sabría la respuesta ;-) –

+0

IMO la respuesta a muchas preguntas es evitar entrar en la situación dolorosa para empezar. –

1

Según una lista de Supported Code Changes, no puede agregar campos a los tipos existentes. Los métodos anónimos se compilan en clases con nombres extraños (un poco <>_c__DisplayClass1), que son precisamente eso: tipos. Aunque sus modificaciones en el método anónimo pueden no incluir cambiar el conjunto de variables adjuntas (al sumarlas alterarían los campos de una clase existente), supongo que esa es la razón por la que es imposible modificar los métodos anónimos.

+1

No tiene que modificar el método anónimo para que se manifieste este problema, basta con modificar un método que _contiene_ un método anónimo, y parece que incluso un solo espacio es suficiente para marcarlo ... – Eyvind

1

que es un poco una pena que esta característica está soportada parcialmente en VB pero no en C#: http://msdn.microsoft.com/en-us/library/bb385795.aspx

Implementar el mismo comportamiento en C# reduciría el nivel de dolor en un 80% para las funciones que contienen expresiones lambda, donde no necesitamos modificar las expresiones lambda ni ninguna expresión que dependa de ellas, y probablemente no sea por un "costo de monstruo".

Cuestiones relacionadas