Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Nota:
Este artículo es una especificación de características. La especificación actúa como documento de diseño de la característica. Incluye cambios de especificación propuestos, junto con la información necesaria durante el diseño y el desarrollo de la característica. Estos artículos se publican hasta que se finalizan los cambios de especificación propuestos y se incorporan en la especificación ECMA actual.
Puede haber algunas discrepancias entre la especificación de características y la implementación completada. Esas diferencias se recogen en las notas de la reunión de diseño de idioma (LDM) pertinentes.
Puede obtener más información sobre el proceso de adopción de especificaciones de características en el estándar del lenguaje C# en el artículo sobre las especificaciones.
Problema planteado por el experto: https://github.com/dotnet/csharplang/issues/2608
Resumen
Aunque la plataforma .NET tiene una característica que admite directamente la escritura de código de inicialización para el ensamblado (técnicamente, el módulo), no se expone en C#. Este es un escenario bastante nicho, pero una vez que se encuentra en ella, las soluciones parecen ser bastante dolorosas. Hay informes de varios clientes (dentro y fuera de Microsoft) que tienen problemas con el problema y no hay más casos no documentados.
Motivación
- Permitir que las bibliotecas realicen una inicialización diligente y única cuando se carguen, con una sobrecarga mínima y sin que el usuario necesite llamar explícitamente a nada
- Un punto de problema concreto de los enfoques actuales
staticdel constructor es que el tiempo de ejecución debe realizar comprobaciones adicionales sobre el uso de un tipo con un constructor estático, para decidir si el constructor estático debe ejecutarse o no. Esto agrega una sobrecarga medible. - Permitir que los generadores de origen ejecuten alguna lógica de inicialización global sin que el usuario necesite llamar explícitamente a nada
Diseño detallado
Un método se puede designar como inicializador de módulo si lo decora con un [ModuleInitializer] atributo .
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
El atributo se puede usar de la siguiente manera:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Algunos requisitos se imponen al método destinado a este atributo:
- El método debe ser
static. - El método debe ser sin parámetros.
- El método debe devolver
void. - El método no debe ser genérico o estar contenido en un tipo genérico.
- El método debe ser accesible desde el módulo contenedor.
- Esto significa que la accesibilidad efectiva del método debe ser
internalopublic. - Esto también significa que el método no puede ser una función local.
- Esto significa que la accesibilidad efectiva del método debe ser
Cuando se encuentran uno o varios métodos válidos con este atributo en una compilación, el compilador emitirá un inicializador de módulo que llama a cada uno de los métodos con atributos. Las llamadas se emitirán en un orden reservado, pero determinista.
Inconvenientes
¿Por qué no deberíamos hacer esto?
- Quizás las herramientas de terceros existentes para inicializadores de módulos de "inyección" son suficientes para los usuarios que han estado solicitando esta característica.
Reuniones de diseño
8 de abril de 2020
C# feature specifications