
En .NET 5, cuando compilas un proyecto, se generan los archivos finales dentro de la carpeta bin\Release\net5.0
de tu proyecto. Dentro de esta encontrarás las DLL de la aplicación, los ejecutables (si los hay), algunos archivos JSON de configuración y los archivos de depuración (.pdb
). Pero además, verás que hay una carpeta llamada ref
que tiene dentro algunas DLL aparentemente iguales a las de tu aplicación. ¿Para qué sirve esa carpeta y sus DLL? ¿La tienes que distribuir con tu aplicación?
IMPORTANTE: en .NET 6, tras bastantes discusiones en GitHub, se decidió que estos ensamblados de referencia se iban a generar de nuevo bajo la carpeta "obj
" y no en "bin
" para evitar confusiones y dado que no tienen un uso muy habitual. No obstante, todo lo demás explicado en este post sigue siendo válido.
Dentro de esta carpeta ref
hay lo que se llaman Reference Assemblies o ensamblados de referencia. Estos ensamblados tan solo contienen la interfaz pública de un ensamblado y los metadatos mínimos sobre la parte pública de los mismos. Esto contrasta con los ensamblados "normales", los que van con tu aplicación, que se denominan ensamblados de implementación.
Los ensamblados de referencia representan un contrato de tu aplicación con el compilador y están atados a una versión concreta. De este modo, si los distribuyes como si fueran una especie de Kit de Desarrollo (SDK) de tu aplicación, otros desarrolladores pueden añadirlos como referencias a sus proyectos y pueden usarlos para compilar contra esa versión específica sin necesidad de tener el código completo. Se suele usar, por ejemplo, si tu aplicación permite plugins o extensiones, para crearlos sin que necesites tener de verdad las DLL finales y pudiendo asegurar que cumplen con lo que espera una versión concreta de tu aplicación. De este modo, no tienes que distribuir el ensamblado, que como sabes, si no está ofuscado es muy fácil de ver su código.
Microsoft los utiliza para sus SDKS. Por ejemplo, .NET Standard proporciona el ensamblado del contrato, netstandard.dll
, que representa el conjunto de APIs comunes compartidas entre distintas plataformas .NET. Las implementaciones de estas API están contenidas en ensamblados diferentes en distintas plataformas, como mscorlib. dll
en .NET Framework o System.Private.CoreLib.dll
en .NET Core. Una biblioteca que tiene como destino .NET Standard puede ejecutarse en todas las plataformas que admiten .NET Standard, y puedes verificar que va a funcionar porque tienes ese contrato en el ensamblado de referencia.
Los ensamblados de referencia deben tener el mismo aspecto que los reales desde el exterior. Por lo tanto, tienen el mismo nombre de archivo, nombre de ensamblado, identidad de ensamblado y todo lo demás, y por eso te parece que están repetidos dentro de la carpeta ref
. Pero no es así. Están ahí para permitir que el sistema de compilación los utilice como sustitutos de los reales. Y dado que estos ensamblados no contienen ninguno de los detalles de implementación (el código real), solo cambian cuando cambia la interfaz de los contenidos.
En tu propio proyecto, MsBuild utiliza estos ensamblados de referencia para acelerar el proceso de compilación, generando y comparando el ensamblado de referencia cada vez que el código compilado cambia.
Si no hay otros proyectos en tu solución que hagan referencia al proyecto concreto que genera esos ensamblados de referencia, realmente no te servirán de mucho, salvo que tengas pensado pasárselos a otros desarrolladores para que los usen como referencia. Así que los puedes borrar. Incluso, si no quieres ni que se generen, puedes desactivar su generación añadiendo esta línea al archivo del proyecto (.csproj
):
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
De este modo ya no se generará la carpeta ref
en las próximas compilaciones.
Te dejo un enlace a la documentación oficial de .NET para esta característica, con muchos más detalles sobre cómo crearlos y utilizarlos: Ensamblados de Referencia en Microsoft Docs.
¡Espero que te resulte útil!