Esta é uma questão levantada por um dos membros da nossa equipe durante o processo de programação. Como esse erro de compilação é fácil de evitar, nunca pensei sobre esse problema com cuidado até olhar seu código e perceber que esse problema não é tão simples.
Dê uma olhada neste código primeiro:
código
programa de aula
{
vazio estático principal(string[] args)
{
byte[] buf = novo byte[1024];
T t = novo T();
stringstr = "1234";
interno n = 1234;
int?nn = 1234;
DateTime dt = DateTime.Agora;
objeto o = 1234;
Console.WriteLine("concluir");
}
}
classe T { }
Quantas variáveis você acha que não são utilizadas neste código?
Se você olhar da perspectiva de um programador, a resposta deveria ser que todas as variáveis não são utilizadas. Mas o resultado dado pelo compilador é um pouco contra-intuitivo:
A variável "str" recebeu um valor, mas seu valor nunca foi usado. A variável "n" recebeu um valor, mas seu valor nunca foi usado. valor nunca foi usado.
O estranho é que embora todas as variáveis sejam declaradas da mesma forma, o compilador apenas pensa que algumas delas não são utilizadas. O que está acontecendo?
Vamos analisá-los um por um. Primeiro observe o array. Se o valor padrão for usado, as informações fornecidas pelo compilador serão diferentes:
byte[] buf1 = null; // Há um aviso
byte[] buf2 = new byte[1024];
Este resultado parece indicar que se a atribuição do parâmetro for nula, o compilador não executará realmente a atribuição e a variável será tratada como se não tivesse sido usada. Os resultados da inspeção IL também podem comprovar esta afirmação: para a primeira linha, o compilador não gerou nenhuma instrução correspondente para a segunda linha, a instrução newattr foi usada para criar o array;
Para aulas personalizadas:
T t1 = null; // Há um aviso
T t2 = new T(); // sem aviso
Este resultado deve ser compreensível (embora seja compreensível, não creio que seja bom, pelas razões apresentadas abaixo). Embora não estejamos chamando nenhum método da classe, o construtor da classe ainda pode realizar algumas operações, portanto, enquanto uma classe for criada, o compilador a tratará como se tivesse sido usada.
Para tipos de valores básicos, seu comportamento é diferente dos tipos de referência. O compilador não trata a atribuição inicial como um uso de variáveis.
int n1 = 0; // Há um aviso
int n2 = 1234; // Há um aviso
int? n3 = null; // Há um aviso
int? n4 = 0; // Há um aviso
int? n5 = 1234; // Há um aviso
String deve ser considerada um tipo de referência em termos de implementação, mas seu desempenho é mais semelhante a um tipo de valor, e as informações de aviso são as mesmas de um tipo de valor.
Para tipos de valores um pouco mais complexos, os resultados são um pouco mais sutis:
DateTime dt1; // Há um aviso
DateTime dt2 = new DateTime(); // Há um aviso
DateTime dt3 = new DateTime(2009,1,1);
DateTime dt4 = DateTime.Now; // sem aviso
Há uma coisa a ser observada sobre esse resultado. Embora o construtor padrão e o construtor parametrizado de DateTime sejam ambos construtores da perspectiva do usuário, eles são diferentes da perspectiva do compilador. Também pode ser visto pela descompilação com IL que se o construtor padrão for chamado, o compilador chama a instrução initobj, enquanto a instrução call ctor é usada para o construtor parametrizado. Além disso, embora o formato do código de atribuição seja exactamente o mesmo do ponto de vista do programador, o compilador adoptará diferentes estratégias de construção dependendo do valor atribuído, o que também é contra-intuitivo.
A conclusão final é lamentável, ou seja, os avisos de compilação do C# não são suficientes para dar proteção suficiente aos programadores, especialmente para arrays:
byte[] buf = novo byte[1024];
Se você construir esse array sem usá-lo, o compilador não fornecerá nenhuma mensagem de aviso ao programador.
Outra questão que vale a pena considerar é declarar uma classe sem usar nenhum método, como apenas
T t = novo T()
Este é um comportamento razoável? O compilador deveria emitir um aviso para isso?
Minha opinião pessoal é que, do ponto de vista do uso, isso não é razoável e deve ser evitado tanto quanto possível. O compilador deve emitir um aviso se descobrir esse uso. Se necessário, você pode evitar mensagens de aviso declarando-as especificamente por meio de diretivas de compilação ou métodos de atributos. No entanto, o comportamento do compilador C# não é emitir avisos, com os quais não concordo. É claro que também espero que todos apresentem as suas próprias ideias.