C# Nomes e Convenções
Na aula anterior você deu nomes às suas variáveis: idade, preco, quantidade. Os nomes que você inventa no código se chamam identificadores, e o C# tem dois tipos de regra para eles. As regras da linguagem são obrigatórias: quebre uma, e o programa não compila. As convenções são combinados da comunidade C#: o programa compila sem elas, mas todo programador espera que você as siga, como espera que um texto em português comece com maiúscula. Nesta aula você aprende as duas, conhece as palavras que não podem ser nomes e o truque do @ para quando você realmente precisa de uma delas.
- O que é um identificador e o que ele pode (e não pode) ter: letras, dígitos,
_, acentos. - Por que
idadeeIdadesão duas coisas diferentes. - As palavras-chave: as reservadas, que nunca podem ser nomes, e as contextuais, que às vezes podem.
- O
@na frente de um nome:@class. - As convenções do C#: camelCase, PascalCase e
_camelCase, e onde cada uma vai. - Como escolher um bom nome, e em que língua.
- Os erros de nome inválido, com a mensagem real e o conserto.
Os programas desta aula foram rodados na máquina fictícia da Ana com o .NET 10 SDK (C# 14), na pasta ~/cs/nomes, com dotnet run arquivo.cs. As saídas foram copiadas da tela.
A ideia: o nome na chamada da escola
Numa sala de aula, cada aluno tem um nome, e a professora chama pelo nome. Há regras que ninguém discute: o nome vai no registro do jeito que está escrito, e "Ana Clara" e "ana clara" são, para o sistema da escola, cadastros diferentes. E há costumes: o nome começa com maiúscula, o sobrenome vem depois.
No C#, é igual. Algumas regras são da linguagem (o compilador confere), outras são costumes (as pessoas conferem). E, como na escola, há nomes que já estão "ocupados": ninguém pode se chamar "Diretoria". No C#, são as palavras-chave.
1. As regras: o que um nome pode ter
Um identificador do C#:
- começa com uma letra ou com
_(sublinhado); - depois, pode ter letras, dígitos (0 a 9) e
_; - não pode ter espaço, hífen, ponto,
$,#nem outros símbolos; - não pode ser uma palavra-chave reservada (seção 3).
int idade = 29;
int idade2 = 30;
int _contador = 0;
int precoTotal = 100;
int maçãs = 3;
Console.WriteLine($"{idade} {idade2} {_contador} {precoTotal} {maçãs}");
$ dotnet run validos.cs 29 30 0 100 3
Todos válidos. Repare no maçãs: o C# aceita letras acentuadas e outras letras do Unicode (o padrão que inclui os alfabetos do mundo inteiro). Mesmo assim, o guia usa nomes sem acento (macas, preco): nem todo teclado, editor e ferramenta lida bem com eles, e o costume da comunidade é evitar. Como o C# diferencia a de á, um acento esquecido também vira um nome diferente.
O que não pode
Um dígito no começo:
int 2lugar = 2; Console.WriteLine(2lugar);
$ dotnet run digito.cs /home/ana/cs/nomes/digito.cs(1,5): error CS1001: Identificador esperado /home/ana/cs/nomes/digito.cs(1,5): error CS1003: Erro de sintaxe, "," esperado /home/ana/cs/nomes/digito.cs(2,22): error CS1003: Erro de sintaxe, "," esperado Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
"Identificador esperado" (Identifier expected): depois do int, o compilador esperava um nome, e encontrou o número 2. Um nome que começa com dígito seria confundido com um número. Conserto: segundoLugar ou lugar2.
Um espaço ou um hífen no meio:
$ dotnet run espaco.cs « int minha idade = 29; /home/ana/cs/nomes/espaco.cs(1,11): error CS1003: Erro de sintaxe, "," esperado Ocorreu uma falha no build. Corrija os erros de build e execute novamente. $ dotnet run hifen.cs « int preco-final = 10; /home/ana/cs/nomes/hifen.cs(1,10): error CS1003: Erro de sintaxe, "," esperado Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
Nos dois casos, o compilador leu o primeiro pedaço como o nome (minha, preco) e não soube o que fazer com o resto. Ele sugere uma vírgula porque int minha, idade declararia duas variáveis (aula Variáveis), mas não é o que você quer. Um espaço separa palavras; um hífen é o sinal de menos: preco-final seria "preco menos final". Conserto: junte as palavras com maiúscula, minhaIdade, precoFinal (seção 5).
E um símbolo:
$ dotnet run cifrao.cs « decimal preco$ = 5m; /home/ana/cs/nomes/cifrao.cs(1,14): error CS1056: Caractere inesperado '$' Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
Missão: nenhum dos três nomes é válido. Troque-os (na declaração e no uso) por segundoLugar, minhaIdade e precoFinal, para o programa compilar e mostrar as três linhas.
Segundo lugar: 2 Idade: 29 Preço final: 10
int 2lugar = 2;
int minha idade = 29;
int preco-final = 10;
Console.WriteLine($"Segundo lugar: {2lugar}");
Console.WriteLine($"Idade: {minha idade}");
Console.WriteLine($"Preço final: {preco-final}");
int segundoLugar = 2;
int minhaIdade = 29;
int precoFinal = 10;
Console.WriteLine($"Segundo lugar: {segundoLugar}");
Console.WriteLine($"Idade: {minhaIdade}");
Console.WriteLine($"Preço final: {precoFinal}");
Repare que, dentro das aspas, Preço final pode ter acento e espaço à vontade: é texto, não nome.
2. Maiúsculas e minúsculas contam
Para o C#, idade e Idade são nomes diferentes, tão diferentes quanto idade e altura:
int idade = 29;
int Idade = 50;
Console.WriteLine($"idade = {idade}, Idade = {Idade}");
$ dotnet run maiusc.cs idade = 29, Idade = 50
Compila, mas é uma péssima ideia: quem lê não sabe qual é qual. E o contrário, declarar com uma forma e usar com outra, é um dos erros mais comuns:
$ dotnet run caso.cs « int Total = 5; Console.WriteLine(total); /home/ana/cs/nomes/caso.cs(2,19): error CS0103: O nome "total" não existe no contexto atual /home/ana/cs/nomes/caso.cs(1,5): warning CS0219: A variável "Total" é atribuída, mas seu valor nunca é usado Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
O erro e o aviso contam a mesma história de dois lados: total (minúsculo) não existe, e Total (maiúsculo) nunca foi usada. As convenções da seção 5 evitam essa confusão: em C#, uma variável sempre começa com minúscula.
3. Palavras-chave: os nomes ocupados
As palavras-chave (keywords) são as palavras da própria linguagem: int, if, class, return… Elas são sempre minúsculas, e os editores as pintam de outra cor. As reservadas nunca podem ser usadas como nome. Veja o que acontece quando a Ana tenta guardar a turma numa variável chamada class ("turma", em inglês):
string class = "3º A"; Console.WriteLine(class);
$ dotnet run chave.cs
/home/ana/cs/nomes/chave.cs(1,8): error CS1001: Identificador esperado
/home/ana/cs/nomes/chave.cs(1,8): error CS1002: ; esperado
/home/ana/cs/nomes/chave.cs(1,14): error CS1001: Identificador esperado
/home/ana/cs/nomes/chave.cs(1,14): error CS1514: { esperado
/home/ana/cs/nomes/chave.cs(1,14): error CS1513: } esperada
/home/ana/cs/nomes/chave.cs(1,14): error CS8803: As instruções de nível superior precisam preceder as declarações de namespace e de tipo.
/home/ana/cs/nomes/chave.cs(1,14): error CS1525: Termo de expressão inválido "="
/home/ana/cs/nomes/chave.cs(2,19): error CS1026: ) esperado
/home/ana/cs/nomes/chave.cs(2,19): error CS1002: ; esperado
/home/ana/cs/nomes/chave.cs(2,24): error CS1001: Identificador esperado
/home/ana/cs/nomes/chave.cs(2,24): error CS1514: { esperado
/home/ana/cs/nomes/chave.cs(2,24): error CS1513: } esperada
/home/ana/cs/nomes/chave.cs(2,24): error CS1022: Definição de namespace ou tipo, ou final do arquivo esperado
Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
Treze erros para duas linhas! Quando o compilador vê class, ele entende "aqui começa a declaração de uma classe" (aula Classes e Objetos) e passa a esperar o nome da classe, uma {, uma }… Nada disso está lá, e cada expectativa frustrada vira uma mensagem. O primeiro erro é o que importa: (1,8): Identificador esperado, exatamente onde está o class. Quando aparecer uma parede de erros estranhos, procure uma palavra-chave usada como nome.
As palavras reservadas
São 77, e você vai conhecer quase todas ao longo do guia. Nenhuma pode ser nome:
abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual void volatile while |
As palavras contextuais
Outras palavras só têm significado especial em certos lugares do código: são as contextuais. Foram acrescentadas à linguagem ao longo dos anos, e para não quebrar programas antigos que já as usavam como nome, o C# continua aceitando-as como identificadores:
int var = 3;
string record = "recorde";
int value = 10;
Console.WriteLine($"{var} {record} {value}");
$ dotnet run contextual.cs 3 recorde 10
Algumas delas: var, value, record, async, await, get, set, init, required, partial, where, yield, nameof, when, with, and, or, not, field. Compila, mas evite: um int var confunde qualquer leitor.
4. O @: uma palavra-chave como nome
Se você precisa mesmo de um nome igual a uma palavra reservada, ponha um @ na frente. O @class é o identificador class, sem o significado de palavra-chave:
string @class = "3º A";
int @int = 5;
Console.WriteLine($"Turma {@class}, sala {@int}");
Console.WriteLine(@class);
$ dotnet run arroba.cs Turma 3º A, sala 5 3º A
O @ não faz parte do nome: ele só avisa o compilador "isto é um nome, não uma palavra-chave". Por isso @idade e idade são a mesma variável:
$ dotnet run mesmo.cs « int @idade = 29; Console.WriteLine(idade); 29
Quando isso é útil? Quase só quando o seu código conversa com outro sistema que já usa esse nome, por exemplo um arquivo JSON com um campo "class" (aula JSON). No seu próprio código, prefira um nome que não precise de @: turma, sala.
@ dos textos
Antes das aspas, como em @"C:\pasta", o @ tem outro papel: ele cria um texto em que a barra invertida não é escape (aula Escapes e Strings Literais). Mesmo símbolo, duas funções: na frente de um nome, ou na frente de um texto.
Missão: o programa não compila porque usa a palavra-chave class como nome. Conserte do jeito que preferir: com o @ (@class) nas duas linhas, ou, melhor ainda, trocando o nome por turma.
string class = "3º A";
Console.WriteLine($"Turma: {class}");
string turma = "3º A";
Console.WriteLine($"Turma: {turma}");
5. As convenções: camelCase e PascalCase
Nomes com várias palavras não podem ter espaço. O jeito do C# de juntá-las é com maiúsculas no começo de cada palavra. Existem dois estilos, e cada um tem o seu lugar:
| Estilo | Como é | Exemplo | Usado em |
|---|---|---|---|
| camelCase | primeira palavra minúscula, as outras com maiúscula (as "corcovas" do camelo) | precoTotal, nomeCliente, idade | variáveis locais e parâmetros de métodos |
| PascalCase | todas as palavras com maiúscula, inclusive a primeira (o estilo da linguagem Pascal) | PrecoTotal, WriteLine, Console | classes, métodos, propriedades, namespaces, constantes, projetos e arquivos |
| _camelCase | camelCase com um _ na frente | _saldo, _nomeCliente | campos privados de uma classe (Nível 2, aula Campos) |
| IPascalCase | PascalCase com um I na frente | IComparable, IDisposable | interfaces (aula Interfaces) |
É por isso que você escreve Console.WriteLine (uma classe e um método do .NET, em PascalCase) e int quantidade (uma variável, em camelCase). Olhando só para o nome, quem conhece as convenções já sabe o que ele é. Este programa usa as três primeiras (as classes são do Nível 2, mas os nomes já dá para ler):
int quantidadeCadernos = 3; // variável: camelCase
decimal precoUnitario = 5.50m; // variável: camelCase
Console.WriteLine(Loja.CalcularTotal(quantidadeCadernos, precoUnitario));
class Loja // classe: PascalCase
{
const int LimiteDeItens = 10; // constante: PascalCase
public static decimal CalcularTotal(int quantidade, decimal preco) // método: PascalCase; parâmetros: camelCase
{
return quantidade * preco;
}
}
$ dotnet run convencoes.cs 16,50
Outras linguagens têm outros costumes: preco_total (snake_case, comum em Python e C), PRECO_TOTAL (tudo maiúsculo, para constantes em C e Java), preco-total (kebab-case, em nomes de arquivos e CSS). Em C#, nenhum deles é usado para nomes de código. Se você vem de outra linguagem, a constante é a armadilha mais comum: em C#, é LimiteDeItens, e não LIMITE_DE_ITENS (aula Constantes).
Siglas
Siglas de duas letras ficam todas maiúsculas (IO, como em System.IO); siglas maiores viram uma palavra comum (Html, Json, Xml, como em System.Text.Json). Em camelCase, a sigla do começo fica toda minúscula: htmlPagina, ioErro.
O compilador não confere convenções
Um int PrecoTotal ou um int preco_total compilam sem nenhum aviso. Quem cobra as convenções são as pessoas, as revisões de código e os editores: o VS Code e o Visual Studio podem sublinhar nomes fora do padrão (com o aviso IDE1006, quando o projeto tem regras de estilo configuradas) e oferecem o Renomear (F2), que troca um nome em todos os lugares onde ele aparece de uma vez.
6. Como escolher um bom nome
O nome é a primeira documentação do código. Um bom nome dispensa comentários (aula Comentários).
| Evite | Prefira | Por quê |
|---|---|---|
x, a, valor | precoTotal, idadeAluno | Diga o que está guardado. |
qtd, prc, nmCli | quantidade, preco, nomeCliente | Abreviações economizam letras e custam entendimento. O editor completa os nomes longos para você. |
strNome, intIdade | nome, idade | Não ponha o tipo no nome: o tipo já está na declaração, e o editor o mostra. |
aberto2, flag | lojaAberta, temDesconto, estaPago | Para bool, um nome que se lê como pergunta de sim ou não. |
dados, coisa, temp | notasDaTurma, proximoCliente | Nomes genéricos não dizem nada. |
idade e Idade juntos | nomes realmente diferentes | Diferença só de maiúscula confunde. |
Nomes de uma letra têm o seu lugar: i num laço curto (aula for), x e y para coordenadas. Fora disso, escreva por extenso.
Português ou inglês?
Tudo o que vem do .NET está em inglês (Console, WriteLine, Length), e em empresas e projetos abertos os nomes costumam ser em inglês também, para qualquer pessoa do mundo entender. Neste guia, os nomes que você cria estão em português (preco, quantidade), para o código se ler como uma frase enquanto você aprende. Qualquer que seja a escolha, a regra de ouro é a mesma: uma língua só no mesmo programa, e sem acento.
Quando dá errado
error CS1001: Identificador esperado
O que significa: o compilador esperava um nome naquele ponto e encontrou outra coisa: um número (2lugar) ou uma palavra-chave (class, int, new). Em inglês: Identifier expected.
Como consertar: comece o nome com uma letra, ou troque a palavra-chave por outro nome (ou ponha @ na frente).
error CS1003: Erro de sintaxe, "," esperado numa declaração
O que significa: um nome com espaço (minha idade) ou com hífen (preco-final). O compilador pegou só a primeira parte como nome.
Como consertar: junte as palavras em camelCase: minhaIdade, precoFinal.
error CS1056: Caractere inesperado '$'
O que significa: um símbolo no nome: $, #, %, ?…
Como consertar: só letras, dígitos e _. Em vez de preco$, precoEmReais.
error CS0103: O nome "total" não existe no contexto atual (e a variável existe!)
O que significa: a declaração e o uso estão escritos de jeitos diferentes: Total e total, preco e preço.
Como consertar: copie o nome da declaração. Seguir a convenção (variáveis sempre em camelCase, sem acento) evita o problema.
O que significa: provavelmente uma palavra-chave usada como nome, como no chave.cs (treze erros por causa de um class).
Como consertar: leia o primeiro erro (aula Lendo Erros do Compilador) e veja que palavra está na posição dele.
Referência rápida
| Regra ou convenção | Certo | Errado (ou fora do padrão) |
|---|---|---|
Começa com letra ou _ | lugar2, _total | 2lugar (CS1001) |
Só letras, dígitos e _ | precoFinal | preco-final, minha idade (CS1003), preco$ (CS1056) |
| Maiúsculas contam | total ≠ Total | declarar Total e usar total (CS0103) |
| Palavra reservada não é nome | turma ou @class | class (CS1001 e muitos outros) |
| Variáveis e parâmetros: camelCase | nomeCliente | NomeCliente, nome_cliente |
| Classes, métodos, propriedades, constantes, namespaces: PascalCase | CalcularTotal, LimiteDeItens | calcularTotal, LIMITE_DE_ITENS |
| Campos privados: _camelCase | _saldo | saldo_, m_saldo |
| Interfaces: I + PascalCase | IComparable | Comparable |
| Nomes descritivos, sem abreviação | quantidade | qtd, x |
Exercícios
1. camelCase
Escreva o nome da variável "nota da prova" em camelCase, sem acento:
2. PascalCase
Escreva o nome do método "calcular média" em PascalCase, sem acento:
3. O @
Complete para usar a palavra-chave new como nome de variável:
4. Qual destes nomes é inválido em C#?
5. Qual destes nomes segue a convenção do C# para uma variável local?
6. int var = 3; compila?
7. Depois de int @idade = 29;, o que mostra Console.WriteLine(idade);?
Missão final: o código da Ana, nas convenções
Missão: o programa funciona, mas os nomes estão fora das convenções do C#. Renomeie, em todos os lugares: NOMECLIENTE para nomeCliente, qtd para quantidade, Preco_Unitario para precoUnitario e x para valorTotal. A saída não pode mudar.
Cliente: Bia Total: 33,00
string NOMECLIENTE = "Bia";
int qtd = 6;
decimal Preco_Unitario = 5.50m;
decimal x = qtd * Preco_Unitario;
Console.WriteLine($"Cliente: {NOMECLIENTE}");
Console.WriteLine($"Total: {x}");
string nomeCliente = "Bia";
int quantidade = 6;
decimal precoUnitario = 5.50m;
decimal valorTotal = quantidade * precoUnitario;
Console.WriteLine($"Cliente: {nomeCliente}");
Console.WriteLine($"Total: {valorTotal}");
Leia as duas versões em voz alta. A segunda conta o que o programa faz; a primeira obriga o leitor a adivinhar o que é x.
Resumo
- Um identificador é um nome que você cria. Começa com letra ou
_, depois letras, dígitos e_. Sem espaço, hífen ou símbolos (CS1001,CS1003,CS1056). Acentos são aceitos, mas o guia não usa. - Maiúsculas contam:
totaleTotalsão nomes diferentes (CS0103quando se mistura). - As 77 palavras-chave reservadas (
class,int,if…) não podem ser nomes; as contextuais (var,value,record…) podem, mas confundem. @na frente transforma uma palavra-chave em nome:@class. O@não faz parte do nome.- Convenções: camelCase para variáveis e parâmetros; PascalCase para classes, métodos, propriedades, constantes, namespaces e projetos;
_camelCasepara campos privados;I+ PascalCase para interfaces. O compilador não confere; as pessoas, sim. - Bons nomes dizem o que guardam, sem abreviações nem o tipo no nome. Uma língua só por programa.