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.

Você vai aprender
  • 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 .xml de 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.

O atalho dos editores

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é");
Código comentado não é para ficar

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 name tem de ser exatamente o nome do parâmetro. Uma etiqueta param para 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:

EtiquetaPara 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
O editor escreve o esqueleto para você

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]
AvisoO que quer dizerConserto
CS1591Um método public (visível para quem usa a classe) está sem ///: o Dobro.Escrever o /// do Dobro.
CS1570XML "mal formado": o <summary> do Soma não foi fechado.Fechar com </summary>.
CS1572Há um <param name="valor">, mas o parâmetro se chama preco.Trocar para name="preco".
CS1573O mesmo engano visto pelo outro lado: o parâmetro preco ficou sem <param>.O mesmo conserto resolve os dois.
CS1587O /// 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 os TODO do 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 //.

Erros estranhos depois de um */

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 '/'.

"Comentei a linha, mas o texto continua aparecendo"

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

EscritaO que é
// textoComentário de linha: até o fim da linha
instrução; // textoComentá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:

Programa da Ana

2. Bloco

Complete o fim do comentário de bloco:

/* Versão 1 da lojinha

3. Documentação

Qual etiqueta guarda o resumo de um método num comentário ///? (Só o nome, sem os sinais.)

/// <>Calcula o total.</…>

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; o GenerateDocumentationFile gera o .xml e liga os avisos CS1591, CS1570, CS1572, CS1573 e CS1587.
  • Comente o porquê, não o óbvio, e mantenha os comentários em dia.