Compara dos versiones de un ensamblado .NET con Glass.NET
Tienes la v1.2.0 y la v1.3.0 de una DLL y necesitas saber exactamente qué cambió — APIs nuevas, un método alterado en silencio, una llamada de red recién añadida — sin el código fuente y sin ejecutar ninguna de las dos compilaciones. Así se comparan dos versiones de un ensamblado en Glass.NET, el decompilador de .NET gratuito y de solo análisis estático.
Tienes la v1.2.0 de una DLL y alguien acaba de pasarte la v1.3.0. Quizá sea una dependencia que tu gestor de paquetes quiere subir, un hotfix que un proveedor te envió por correo, o una actualización de NuGet con un changelog que dice «correcciones de errores y mejoras». Antes de confiar en ella en tu compilación, quieres la respuesta honesta a una sola pregunta: ¿qué cambió realmente?
No lo que afirman las notas de la versión. El diff real — tipos nuevos y eliminados, un cuerpo de método reescrito en silencio, una firma pública que se desplazó, una llamada de red que no estaba en la versión anterior. Y lo quieres sin el código fuente (no lo tienes) y sin ejecutar ninguna de las dos compilaciones (todavía no confías en ellas).
Eso es un trabajo de decompilar-y-comparar, y Glass.NET está hecho para ello. Es gratuito, y es estrictamente estático — lee los metadatos y el IL y reconstruye C#, y nunca ejecuta el ensamblado que inspecciona. Así que puedes comparar con seguridad una actualización de la que no estás seguro: nada de ninguna de las dos DLL se ejecuta. Glass tiene una comparación de ensamblados en paralelo con diff línea a línea que pone las dos versiones una junto a la otra y te muestra el delta directamente, método a método.
Por qué «lee el changelog» no basta
Un changelog es una afirmación, no una prueba. El binario entregado es la fuente de verdad de lo que se ejecuta, y se desvía de la historia por todas las vías habituales:
- El binario no es el repositorio. Un
.nupkges un artefacto compilado descargado de un feed. A menos que sea una compilación verificablemente reproducible, la DLL — no la etiqueta de GitHub — es lo que se ejecuta en tu proceso. - Las subidas de parche esconden cambios reales. Una versión de «corrección de errores» puede añadir una nueva llamada saliente, cambiar cómo se valida un valor o alterar un valor por defecto. El versionado semántico es una convención, no una garantía.
- Los cambios incompatibles se escapan en silencio. Un método público que cambió de firma sin avisar o que desapareció romperá a quien lo llame en tiempo de ejecución, aun cuando el número de versión diga «subida menor segura».
Leer el delta tú mismo es un seguro barato, y es la misma disciplina que inspeccionar un paquete NuGet antes de confiar en él — salvo que ahora ya confiabas en la versión anterior, así que solo necesitas auditar lo que se movió.
Carga ambas versiones
Pon las dos DLL en disco. Para una dependencia de NuGet están en la caché global de paquetes — %USERPROFILE%\.nuget\packages\<id>\<version>\lib\<tfm>\ en Windows, ~/.nuget/packages/... en el resto — una carpeta por versión, así que puedes coger la 1.2.0 y la 1.3.0 en paralelo. Para una entrega de un proveedor o tu propia salida, basta con apuntar a los dos archivos.
Abre el primer ensamblado en Glass.NET (arrástralo a la ventana, o Archivo ▸ Abrir ensamblado), y luego abre el segundo. Cada uno aparece como un árbol de espacios de nombres ▸ tipos ▸ miembros, con C# legible reconstruido bajo demanda — sin PDB, sin Source Link, sin compilación especial.
Ejecuta la comparación de ensamblados
Inicia la comparación de ensamblados de Glass.NET y elige las dos versiones como el lado antiguo y el nuevo. Glass decompila ambos y muestra un diff línea a línea del C# reconstruido, alineado para que leas la diferencia directamente en vez de ir saltando entre dos ventanas y fiarte de tu memoria. Este es el núcleo del flujo de trabajo: revisas el delta, no relees toda la biblioteca.
Recórrelo con preguntas concretas.
1. ¿Qué tipos y miembros aparecieron o desaparecieron?
Empieza por el nivel estructural, antes de cualquier cuerpo de método. La comparación saca a la luz los tipos y miembros que son nuevos en la v1.3.0, que ya no están, o que cambiaron. Pregúntate qué significa cada uno:
- Un tipo nuevo — especialmente uno que toca E/S, serialización o control de procesos — es lo primero que hay que entender. Un ayudante de logging es rutina; un nuevo
*Cliento*Uploaderen una biblioteca que no tenía motivo para hablar con la red merece una mirada dura. - Un tipo o miembro eliminado es una señal de compatibilidad. Si tu código lo referenciaba, la subida te rompe — mejor enterarte aquí que por un
MissingMethodExceptionen tiempo de ejecución. - Un campo nuevo o eliminado en un tipo que serializas puede cambiar en silencio los formatos en disco o en la red.
2. ¿Cambió la superficie de API pública?
Céntrate en la superficie pública — el contrato del que depende todo lo que está aguas abajo. Despliega los tipos y miembros públicos en ambos lados y deja que la comparación muestre qué se añadió, se quitó o se refirmó:
// v1.2.0
public Result Process(string input)
// v1.3.0
public Result Process(string input, CancellationToken token = default)
Un parámetro opcional añadido así suele ser compatible a nivel de código fuente pero no a nivel binario — quien lo llame debe recompilar, y un plugin cargado contra la firma antigua fallará. Un método público eliminado, un tipo de retorno cambiado o un parámetro que perdió su valor por defecto es una ruptura más dura. El sentido de comparar específicamente la superficie pública es que ahí es donde una subida de versión «menor» hace el daño sobre el que menos honesta es.
3. ¿Qué cambió dentro de un cuerpo de método?
Para un método que existe en ambas versiones, el diff línea a línea muestra exactamente cómo cambió su C# reconstruido. Aquí es donde cazas la reescritura silenciosa — lo que ningún changelog menciona:
- Una comprobación de validación que se quitó o se aflojó.
- Una constante, límite o valor por defecto codificado que se movió.
- Una nueva rama que llama a algo — un archivo, una clave del registro, una URL.
La captura de mayor valor aquí es una nueva llamada de red o un lanzamiento de proceso que la versión anterior no tenía. Si la v1.3.0 de un ayudante de formateo de fechas de repente construye un HttpClient y hace POST a un endpoint codificado, el diff te pone esas líneas exactas delante. Es la misma caza de señales de alarma que cubre analizar un ensamblado .NET sospechoso — el diff solo la reduce a lo que es nuevo.
4. Lee el IL donde el C# sea ambiguo
El C# decompilado es una reconstrucción, y dos compilaciones genuinamente distintas pueden de vez en cuando producir C# que parece igual, o diferir solo de una forma que la vista de C# redondea — una resolución de sobrecarga cambiada, un salto entre == y object.Equals, una máquina de estados generada por el compilador que se reorganizó. Cuando el diff de C# de un método parece sospechosamente vacío o sospechosamente ruidoso y necesitas certeza, cambia a la vista de IL de Glass.NET y compara el IL directamente. El IL es lo que de verdad se ejecuta, así que es la verdad de base; leer el IL es el desempate cuando el C# es ambiguo. Para la mayoría de los métodos el diff de C# sobra — recurre al IL en el puñado donde importa.
Usa el informe de exposición como filtro rápido
Glass.NET también produce un informe de exposición que resume cuánto de un ensamblado es legible. Pásalo sobre ambas versiones como señal rápida de triaje: si de repente la v1.3.0 reporta mucho menos legible que la v1.2.0, una dependencia antes clara puede haber empezado a entregar código ofuscado o virtualizado — lo cual, en una biblioteca de estilo open source corriente, es ya un motivo para parar y preguntar por qué. (Si estás en el otro lado de esto — protegiendo tu propia compilación — para eso está el ofuscador hermano Nebula.NET, y la virtualización de código es una función Pro; entonces verificarías el resultado en Glass.)
Conoce los límites
Comparar dos versiones te dice con precisión qué cambió en los bytes que tienes — no te dice si un cambio es seguro, solo cuál es; ese juicio sigue siendo tuyo. La lectura estática no sacará a la luz comportamientos que solo aparecen en tiempo de ejecución con entradas concretas, y el código muy ofuscado puede no reconstruirse limpio en ninguno de los dos lados (de nuevo, una señal en sí misma). Y estás comparando dos compilaciones concretas: fija tus dependencias y vuelve a comparar en cada actualización, para que el delta sea siempre lo bastante pequeño como para leerlo de verdad.
Ese es justo el objetivo. En vez de reauditar una biblioteca entera en cada subida, revisas solo lo que se movió — APIs nuevas, miembros eliminados, cuerpos reescritos, una llamada de red recién añadida — en una herramienta gratuita y de solo análisis estático que nunca ejecuta una línea de ninguna de las dos compilaciones. Descarga Glass.NET, carga ambas versiones y lee el diff antes de confiar en la nueva.
Prueba Nebula.NET
Endurece tu código .NET en minutos — empieza con la edición gratuita.