C# Comentários
Um programa é lido muito mais vezes do que é escrito: por você mesma daqui a um mês, por um colega, por quem for consertar um erro. Os comentários são anotações que você deixa no código para essas pessoas. O compilador as ignora por completo: elas não mudam em nada o que o programa faz. Nesta aula você aprende os três tipos de comentário do C#: o de linha (//), o de bloco (/* */) e o de documentação (///), que vira a ajuda que aparece no editor quando alguém usa o seu código.
- O comentário de linha,
//, sozinho na linha ou no fim de uma instrução. - O comentário de bloco,
/* … */, de várias linhas ou no meio de uma linha. - Como "desligar" um pedaço de código comentando-o, e o atalho dos editores.
- O que parece comentário e não é:
//dentro de um texto. - Os comentários de documentação
///:<summary>,<param>e<returns>. - O arquivo
.xmlde documentação e os avisos que conferem os///. - O que vale a pena comentar e o que não vale.
Os programas desta aula foram rodados na máquina fictícia da Ana com o .NET 10 SDK (C# 14), na pasta ~/cs/comentarios com dotnet run arquivo.cs e num projeto em ~/projetos/Doc. As saídas foram copiadas da tela.
A ideia: os post-its no caderno de receitas
A avó da Ana tem um caderno de receitas cheio de post-its colados: "usar a forma grande", "a tia gosta com menos açúcar", "não funciona com farinha integral". Os post-its não fazem parte da receita (quem cozinha não "executa" um post-it), mas explicam escolhas e evitam erros.
Um comentário é um post-it no código. O compilador passa por ele sem ler, e o programa gerado é idêntico com ou sem comentários.
1. Comentário de linha: //
Duas barras, //, começam um comentário que vai até o fim da linha. Ele pode ocupar a linha inteira ou vir depois de uma instrução:
// Programa da lista de compras da Ana
Console.WriteLine("Arroz"); // 5 kg
// Console.WriteLine("Feijão");
Console.WriteLine("Café");
Console.WriteLine("// isto não é comentário");
$ dotnet run linha.cs Arroz Café // isto não é comentário
- // Programa da lista…
- Uma linha inteira de comentário: uma explicação para quem lê. Não gera saída nenhuma.
- …("Arroz"); // 5 kg
- Comentário no fim de uma linha: a instrução antes do
//roda normalmente; o resto da linha é ignorado. - // Console.WriteLine("Feijão");
- Uma instrução comentada: como começa com
//, ela virou comentário e não roda. Repare que o Feijão sumiu da saída. - "// isto não é comentário"
- Dentro de um texto entre aspas,
//são só dois caracteres. O texto aparece inteiro na saída, com as barras.
Esse é o comentário mais usado em C#. Repare no costume: um espaço depois do //, e frases curtas.
2. Comentário de bloco: /* … */
Barra e asterisco, /*, começam um comentário que vai até o asterisco e barra, */, que pode estar várias linhas abaixo, ou na mesma linha:
/* Lojinha da Ana
Versão 1: só mostra o nome da loja.
Escrito em outubro. */
Console.WriteLine("Lojinha da Ana");
Console.WriteLine(/* o preço */ "R$ 5");
$ dotnet run bloco.cs Lojinha da Ana R$ 5
- /* Lojinha da Ana … */
- Três linhas de comentário de uma vez. Tudo entre
/*e*/é ignorado, inclusive as quebras de linha. - (/* o preço */ "R$ 5")
- Um comentário de bloco pode ficar no meio de uma linha, porque tem um fim marcado. Funciona, mas atrapalha a leitura; use pouco.
Na prática, o código C# usa pouco o /* */. Para várias linhas, o mais comum é uma sequência de //, uma por linha, que os editores criam com um atalho (seção 3).
O /* precisa do seu */
Se o */ for esquecido, o comentário engole o resto do arquivo:
/* Comentário que esqueceu de fechar
Console.WriteLine("Olá!");
$ dotnet run aberto.cs /home/ana/cs/comentarios/aberto.cs(1,1): error CS1035: Final do arquivo encontrado. '*/' esperado Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
"Final do arquivo encontrado; esperava */". A posição (1,1) aponta onde o comentário começou. Em inglês: End-of-file found, '*/' expected.
Um /* */ não entra dentro de outro
Os comentários de bloco não se aninham (não dá para pôr um dentro do outro). O primeiro */ que aparecer fecha o comentário, mesmo que haja dois /* abertos:
/* fora
/* dentro */
ainda fora? */
Console.WriteLine("Olá!");
$ dotnet run aninhado.cs /home/ana/cs/comentarios/aninhado.cs(3,14): error CS1003: Erro de sintaxe, "," esperado Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
O comentário terminou no */ da linha 2. A linha 3, ainda fora? */, virou código, e o compilador não conseguiu entendê-lo. A mensagem é estranha porque o compilador tentou ler aquelas palavras como C#. É mais um motivo para preferir o //: ele não tem esse problema.
3. Comentar para desligar código
Um uso muito comum dos comentários é desligar uma instrução por um tempo, sem apagá-la: para testar o programa sem ela, ou para procurar qual linha está causando um erro. É o que a Ana fez com o Feijão na seção 1.
No VS Code (e na maioria dos editores), selecione as linhas e aperte Ctrl+/: o editor põe // no começo de cada uma. Apertando de novo, ele tira. Assim você liga e desliga várias linhas de uma vez (aula Editores e IDEs).
Missão: a Ana já comprou o feijão. Comente (não apague) a linha do Feijão, para ela continuar no código mas sair da lista. Depois, se quiser, acrescente um comentário no fim da linha do Arroz, como // 5 kg, e veja que a saída não muda.
Console.WriteLine("Lista da Ana");
Console.WriteLine("Arroz");
Console.WriteLine("Feijão");
Console.WriteLine("Café");
Console.WriteLine("Lista da Ana");
Console.WriteLine("Arroz"); // 5 kg
// Console.WriteLine("Feijão");
Console.WriteLine("Café");
Desligar uma linha para testar é ótimo. Mas, quando o teste acabar, decida: ou a linha volta, ou ela é apagada. Código comentado esquecido confunde quem lê ("isso é importante? posso apagar?"). Quando você aprender a usar o Git, ele guarda as versões antigas para você, e não é preciso deixar nada comentado "para garantir".
4. Comentários de documentação: ///
Três barras, ///, fazem um comentário especial, de documentação. Ele fica logo acima de uma classe ou de um método e explica, num formato fixo, o que aquilo faz. Os editores leem esse formato: quando alguém usa o método, a explicação aparece numa caixinha ao passar o mouse, e enquanto digita.
Métodos e classes são assunto do Nível 2 (Métodos e Classes e Objetos). Aqui, leia o código como uma ferramenta da lojinha: a classe Loja tem um método ComDesconto, que recebe um preço e um desconto e devolve o preço a pagar.
Console.WriteLine(Loja.ComDesconto(50m, 8m));
/// <summary>Ferramentas da lojinha da Ana.</summary>
static class Loja
{
/// <summary>
/// Calcula o preço com desconto.
/// </summary>
/// <param name="preco">O preço cheio, em reais.</param>
/// <param name="desconto">O desconto, em reais.</param>
/// <returns>O preço a pagar.</returns>
public static decimal ComDesconto(decimal preco, decimal desconto)
{
return preco - desconto;
}
}
$ dotnet run doc2.cs 42
O programa mostra 42 (50 menos 8), e os ///, como qualquer comentário, não mudam nada na saída. Dentro deles, o texto vai entre etiquetas XML, no mesmo estilo do .csproj (aula Projetos): uma etiqueta abre (<summary>) e outra, com barra, fecha (</summary>).
- /// <summary> … </summary>
- O resumo: uma ou duas frases dizendo o que a classe ou o método faz. É a etiqueta mais importante, e a que aparece primeiro na caixinha do editor.
- /// <param name="preco"> … </param>
- A explicação de um parâmetro (um valor que o método recebe). O
nametem de ser exatamente o nome do parâmetro. Uma etiquetaparampara cada um. - /// <returns> … </returns>
- O que o método devolve (returns = "retorna").
- static class Loja
- O elemento documentado vem logo depois dos
///, sem linha de código no meio.
Outras etiquetas úteis:
| Etiqueta | Para quê |
|---|---|
<summary> | O resumo (sempre) |
<param name="x"> | Um parâmetro |
<returns> | O valor devolvido |
<remarks> | Observações mais longas, além do resumo |
<example> e <code> | Um exemplo de uso |
<exception cref="…"> | Que erro (exceção) o método pode lançar (aula throw) |
<see cref="Loja"/> | Um link para outro elemento do código |
<paramref name="preco"/> | Cita um parâmetro no meio do texto |
No Visual Studio e no VS Code com a extensão C# Dev Kit, digite /// na linha de cima de um método: o editor cria sozinho o <summary>, um <param> para cada parâmetro e o <returns>. Você só preenche os textos.
Onde o /// pode ficar
Os comentários de documentação servem para classes e seus membros (métodos, propriedades…). Uma função solta, escrita junto das instruções de nível superior (aula Program.cs e o Main), não é documentável. Num projeto que gera documentação (logo abaixo), o compilador avisa:
Console.WriteLine(Dobro(21));
/// <summary>
/// Calcula o dobro de um número.
/// </summary>
/// <param name="numero">O número que vai ser dobrado.</param>
/// <returns>O número vezes 2.</returns>
int Dobro(int numero)
{
return numero * 2;
}
$ dotnet build 2>&1 | grep warning | sort -u /home/ana/projetos/Doc/Program.cs(3,1): warning CS1587: O comentário XML não está inserido em um elemento de linguagem válido [/home/ana/projetos/Doc/Doc.csproj]
"O comentário XML não está num elemento válido" (XML comment is not placed on a valid language element). É só um aviso: o programa funciona (mostra 42), mas o /// ali é inútil. Para uma função solta, use //.
Missão: o método ComDesconto está sem documentação. Escreva, logo acima da linha public static decimal ComDesconto, um comentário /// com <summary>, um <param> para preco, outro para desconto e um <returns>. Use o comentário da classe como modelo. A saída não muda: Total: R$ 42,00.
Console.WriteLine($"Total: {Loja.ComDesconto(50m, 8m):C}");
/// <summary>Ferramentas da lojinha da Ana.</summary>
static class Loja
{
public static decimal ComDesconto(decimal preco, decimal desconto)
{
return preco - desconto;
}
}
Console.WriteLine($"Total: {Loja.ComDesconto(50m, 8m):C}");
/// <summary>Ferramentas da lojinha da Ana.</summary>
static class Loja
{
/// <summary>Calcula o preço com desconto.</summary>
/// <param name="preco">O preço cheio, em reais.</param>
/// <param name="desconto">O desconto, em reais.</param>
/// <returns>O preço a pagar.</returns>
public static decimal ComDesconto(decimal preco, decimal desconto)
{
return preco - desconto;
}
}
5. O arquivo de documentação e os avisos
Por padrão, o compilador trata os /// como comentários comuns e nem confere o que está escrito neles. Para que ele confira e gere um arquivo com a documentação, ligue a opção GenerateDocumentationFile ("gerar arquivo de documentação") no .csproj:
$ cat Doc.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile> « a linha nova
</PropertyGroup>
</Project>
Depois do dotnet build, aparece um Doc.xml ao lado do Doc.dll, em bin/Debug/net10.0. É ele que os editores leem para mostrar a ajuda de uma biblioteca, e é assim que a ajuda do próprio Console.WriteLine chega até você. (Num arquivo solto, a mesma opção se liga com a linha #:property GenerateDocumentationFile=true no topo do .cs. Linhas com #: não são comentários: são diretivas para o dotnet run, explicadas em Rodar com dotnet run.)
Com a opção ligada, o compilador vira um revisor da documentação. A Ana escreveu mais métodos no arquivo Loja.cs do projeto, cada um com um descuido:
public static decimal Dobro(decimal preco)
{
return preco * 2;
}
/// <summary>Soma dois preços.
public static decimal Soma(decimal a, decimal b) => a + b;
/// <summary>Mostra o preço.</summary>
/// <param name="valor">O valor.</param>
public static void Mostrar(decimal preco) => Console.WriteLine(preco);
$ dotnet build 2>&1 | grep warning | sort -u /home/ana/projetos/Doc/Loja.cs(13,27): warning CS1591: Comentário XML ausente para tipo publicamente visível ou membro "Loja.Dobro(decimal)" [/home/ana/projetos/Doc/Doc.csproj] /home/ana/projetos/Doc/Loja.cs(19,1): warning CS1570: O comentário XML tem XML com formação incorreta -- "Espera-se uma tag de fim para o elemento "summary"." [/home/ana/projetos/Doc/Doc.csproj] /home/ana/projetos/Doc/Loja.cs(22,22): warning CS1572: Comentário XML tem uma tag param para "valor", mas não há parâmetro por esse nome [/home/ana/projetos/Doc/Doc.csproj] /home/ana/projetos/Doc/Loja.cs(23,40): warning CS1573: Parâmetro "preco" não tem tag param correspondente no comentário XML para "Loja.Mostrar(decimal)" (mas outros parâmetros têm) [/home/ana/projetos/Doc/Doc.csproj] /home/ana/projetos/Doc/Program.cs(3,1): warning CS1587: O comentário XML não está inserido em um elemento de linguagem válido [/home/ana/projetos/Doc/Doc.csproj]
| Aviso | O que quer dizer | Conserto |
|---|---|---|
CS1591 | Um método public (visível para quem usa a classe) está sem ///: o Dobro. | Escrever o /// do Dobro. |
CS1570 | XML "mal formado": o <summary> do Soma não foi fechado. | Fechar com </summary>. |
CS1572 | Há um <param name="valor">, mas o parâmetro se chama preco. | Trocar para name="preco". |
CS1573 | O mesmo engano visto pelo outro lado: o parâmetro preco ficou sem <param>. | O mesmo conserto resolve os dois. |
CS1587 | O /// da função solta do Program.cs (seção 4). | Trocar por //. |
São só avisos (o programa é gerado), mas vale consertar todos: uma documentação errada engana quem a lê. Avisos em geral são o assunto da aula Avisos do Compilador. Bibliotecas que outras pessoas vão usar costumam ligar o GenerateDocumentationFile; programas pequenos, como os do Nível 1, não precisam.
6. O que comentar (e o que não)
Comentário bom explica por que; o código já mostra o que. Compare:
// RUIM: repete o que o código já diz
Console.WriteLine("Arroz"); // escreve Arroz
// BOM: explica uma decisão que o código não mostra
// A feira só aceita pedidos até 10 itens, por isso a lista para aqui.
Console.WriteLine("Fim da lista");
- Comente o porquê: uma regra do negócio, um cuidado, uma escolha que parece estranha.
- Não comente o óbvio. Se o código precisa de um comentário para dizer o que faz, talvez os nomes possam ser melhores (aula Nomes e Convenções).
- Mantenha os comentários atualizados. Um comentário que contradiz o código é pior do que nenhum.
- Marque pendências com
// TODO:("a fazer"):// TODO: aceitar pagamento com cartão. Os editores listam todos osTODOdo projeto. - Documente com
///o que outras pessoas vão usar: classes e métodos públicos.
Quando dá errado
error CS1035: Final do arquivo encontrado. '*/' esperado
O que significa: um /* nunca foi fechado, e o comentário engoliu o resto do arquivo. A posição aponta o /*.
Como consertar: feche com */ no lugar certo, ou troque o bloco por linhas de //.
*/
O que significa: um /* */ dentro de outro. O primeiro */ fechou o comentário, e o texto depois dele virou código (o aninhado.cs deu CS1003: Erro de sintaxe, "," esperado).
Como consertar: não ponha um /* */ dentro de outro. Para desligar um trecho que já tem comentários, use Ctrl+/, que põe // em cada linha.
error CS1525: Termo de expressão inválido "/"
O que significa: o comentário foi escrito com uma barra só (/ Comentário). Uma barra só é o sinal de divisão, e o compilador tentou fazer uma conta:
$ dotnet run barras.cs « / Comentário com uma barra só /home/ana/cs/comentarios/barras.cs(1,1): error CS1525: Termo de expressão inválido "/" /home/ana/cs/comentarios/barras.cs(1,14): error CS1002: ; esperado /home/ana/cs/comentarios/barras.cs(1,22): error CS1003: Erro de sintaxe, "," esperado Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
Como consertar: duas barras: //. Em inglês, a primeira mensagem é Invalid expression term '/'.
O que significa: o // ficou dentro das aspas (Console.WriteLine("// Feijão");). Ali ele faz parte do texto.
Como consertar: o // vai no começo da linha, antes do Console.
warning CS1591, CS1570, CS1572, CS1573, CS1587
O que significa: avisos sobre os comentários ///. Só aparecem com o GenerateDocumentationFile ligado (seção 5).
Como consertar: veja a tabela da seção 5. O mais comum é o nome do <param> diferente do nome do parâmetro.
Referência rápida
| Escrita | O que é |
|---|---|
// texto | Comentário de linha: até o fim da linha |
instrução; // texto | Comentário no fim de uma linha de código |
/* texto */ | Comentário de bloco: até o */, em uma ou várias linhas; não aninha |
/// <summary>…</summary> | Comentário de documentação, acima de classes e membros |
/// <param name="x">…</param> | Documenta o parâmetro x |
/// <returns>…</returns> | Documenta o que o método devolve |
<GenerateDocumentationFile>true</GenerateDocumentationFile> | No .csproj: gera o .xml e confere os /// |
// TODO: … | Marca uma pendência |
| Ctrl+/ | Comenta e descomenta as linhas selecionadas (VS Code) |
"// texto" | Não é comentário: é um texto com duas barras |
Exercícios
1. Linha
Complete para que a linha seja um comentário:
2. Bloco
Complete o fim do comentário de bloco:
3. Documentação
Qual etiqueta guarda o resumo de um método num comentário ///? (Só o nome, sem os sinais.)
4. O que mostra este programa? Console.WriteLine("A"); // Console.WriteLine("B");
5. E este? Console.WriteLine("Preço // promoção");
6. Um método tem o parâmetro preco, e o comentário diz <param name="valor">. Com o GenerateDocumentationFile ligado, o que acontece?
7. Qual destes comentários é mais útil?
Missão final: o programa comentado
Missão: este programa não compila, e os comentários são os culpados: um comentário de bloco sem fim e uma linha que deveria estar desligada mas usa uma barra só. Conserte os dois e acrescente, no topo, um comentário de linha seu explicando o que o programa faz. A saída deve ser:
Lojinha da Ana Caderno: R$ 12
/* Versão 2 da lojinha.
Mostra o nome e o preço do caderno.
Console.WriteLine("Lojinha da Ana");
Console.WriteLine("Caderno: R$ 12");
/ Console.WriteLine("Caneta: R$ 3");
// Mostra a lojinha da Ana e o preço do caderno.
/* Versão 2 da lojinha.
Mostra o nome e o preço do caderno. */
Console.WriteLine("Lojinha da Ana");
Console.WriteLine("Caderno: R$ 12");
// Console.WriteLine("Caneta: R$ 3");
Resumo
- Comentários são anotações para pessoas. O compilador os ignora, e o programa fica igual com ou sem eles.
//comenta até o fim da linha, sozinho ou depois de uma instrução. É o mais usado./* … */comenta um bloco, de uma ou várias linhas. Precisa do*/(CS1035) e não aninha.- Comentar uma instrução a desliga (Ctrl+/ no editor). Depois do teste, volte com ela ou apague.
- Dentro de aspas,
//e/*são texto, não comentário. ///documenta classes e membros com etiquetas XML:<summary>,<param name="…">,<returns>. Os editores mostram essa ajuda; oGenerateDocumentationFilegera o.xmle liga os avisosCS1591,CS1570,CS1572,CS1573eCS1587.- Comente o porquê, não o óbvio, e mantenha os comentários em dia.