Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ela inclui alterações de especificação propostas, juntamente com as informações necessárias durante o design e o desenvolvimento do recurso. Esses artigos são publicados até que as alterações de especificação propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas divergências entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas LDM (reunião de design de idioma) pertinentes.
Você pode saber mais sobre o processo de adoção de especificações de recursos no padrão de linguagem C# no artigo sobre as especificações.
Problema do especialista: https://github.com/dotnet/csharplang/issues/2608
Resumo
Embora a plataforma .NET tenha um recurso que dá suporte direto à gravação de código de inicialização para o assembly (tecnicamente, o módulo), ele não é exposto em C#. Este é um cenário bastante específico, mas uma vez que você se depara com ele, as soluções parecem ser bastante dolorosas. Há relatos de vários clientes (dentro e fora da Microsoft) lutando com o problema e, sem dúvida, há mais casos não documentados.
Motivação
- Permitir que as bibliotecas façam uma inicialização única e ansiosa quando carregadas, com sobrecarga mínima e sem que o usuário precise chamar nada explicitamente
- Um ponto problemático específico das abordagens atuais
staticdo construtor é que o runtime deve fazer verificações adicionais sobre o uso de um tipo com um construtor estático, a fim de decidir se o construtor estático precisa ser executado ou não. Isso adiciona sobrecarga mensurável. - Permitir que os geradores de origem executem alguma lógica de inicialização global sem que o usuário precise chamar explicitamente nada
Design detalhado
Um método pode ser designado como um inicializador de módulo decorando-o com um [ModuleInitializer] atributo.
using System;
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class ModuleInitializerAttribute : Attribute { }
}
O atributo pode ser usado assim:
using System.Runtime.CompilerServices;
class C
{
[ModuleInitializer]
internal static void M1()
{
// ...
}
}
Alguns requisitos são impostos ao método direcionado com este atributo:
- O método deve ser
static. - O método deve ser sem parâmetros.
- O método deve retornar
void. - O método não deve ser genérico ou estar contido em um tipo genérico.
- O método deve ser acessível a partir do módulo que o contém.
- Isso significa que a acessibilidade efetiva do método deve ser
internaloupublic. - Isso também significa que o método não pode ser uma função local.
- Isso significa que a acessibilidade efetiva do método deve ser
Quando um ou mais métodos válidos com esse atributo são encontrados em uma compilação, o compilador emitirá um inicializador de módulo que chama cada um dos métodos atribuídos. As chamadas serão emitidas em uma ordem reservada, mas determinística.
Desvantagens
Por que não devemos fazer isso?
- Talvez as ferramentas de terceiros existentes para "injetar" inicializadores de módulo sejam suficientes para usuários que solicitam esse recurso.
Reuniões de design
8 de abril de 2020
C# feature specifications