C# Variáveis
Todo programa precisa guardar coisas enquanto trabalha: o nome de quem está usando, o preço de um caderno, quantas maçãs sobraram na lojinha da Ana. Em C#, cada coisa guardada fica numa variável. Nesta aula você vai criar suas primeiras variáveis, mostrar o valor delas, trocar esse valor e conhecer as regras que o compilador do C# cobra com rigor, e que evitam muitos erros: o tipo de uma variável nunca muda, e nenhuma variável pode ser lida antes de receber um valor.
- O que é uma variável e como criar uma:
int idade = 29;. - Como mostrar o valor com
Console.WriteLinee com$"…{idade}…". - Os tipos mais usados no começo:
int,double,decimal,string,boolechar. - Como trocar o valor, copiar de uma variável para outra, e por que o tipo nunca muda.
- Como criar várias variáveis numa linha, e a armadilha que mora ali.
- Por que o C# recusa ler uma variável sem valor (o erro
CS0165). - Os erros de usar uma variável antes de criá-la, de criar duas com o mesmo nome e de usá-la fora do seu bloco.
Todos os programas desta aula foram rodados na máquina fictícia da Ana com o .NET 10 SDK (C# 14), na pasta ~/cs/variaveis, com dotnet run arquivo.cs. A máquina está em português do Brasil, e por isso os números com casas decimais aparecem com vírgula. Você pode repetir cada um no editor do guia, que compila C# de verdade no navegador.
A ideia: uma caixa com etiqueta e formato
Pense numa mudança de casa. Você guarda as coisas em caixas e escreve uma etiqueta em cada uma: "LIVROS", "PANELAS". Quando quer as panelas, procura pela etiqueta.
Uma variável é isso: um pedacinho da memória do computador com uma etiqueta. A etiqueta é o nome; o que está dentro é o valor. O nome "variável" vem daí: o que está dentro pode variar.
Em C#, cada caixa tem também um formato, escolhido quando você a cria, e que nunca muda. Uma caixa de ovos só guarda ovos; uma caixa de sapatos só guarda sapatos. Esse formato se chama tipo.
| Parte da caixa | Nome técnico | Exemplo |
|---|---|---|
| O formato (o que cabe nela) | tipo | int (número inteiro), string (texto) |
| A etiqueta | nome | idade, nome, preco |
| O que está guardado agora | valor | 29, "Ana", 12.50m |
1. Declarar uma variável
Criar uma variável se chama declarar. A receita é sempre a mesma: tipo nome = valor;.
int idade = 29;
Console.WriteLine(idade);
Console.WriteLine($"A Ana tem {idade} anos.");
- int
- O tipo: esta caixa guarda um número inteiro.
intvem de integer, "inteiro". - idade
- O nome da variável. As regras e os costumes de nomes estão em Nomes e Convenções: em C#, variáveis começam com letra minúscula.
- =
- Leia como "recebe": idade recebe 29. Não é o "igual" da matemática; quem compara valores é o
==(aula Operadores de Comparação). - 29
- O valor inicial. Números não levam aspas.
- ;
- O ponto e vírgula termina a declaração, como toda instrução (aula Sintaxe).
- Console.WriteLine(idade);
- Mostra o valor guardado na variável.
- $"A Ana tem {idade} anos."
- A interpolação: com o
$antes das aspas, o que está entre chaves é trocado pelo valor (aula Interpolação). É o jeito mais prático de pôr variáveis no meio de um texto.
$ dotnet run idade.cs 29 A Ana tem 29 anos.
O programa mostrou o valor, e não a palavra "idade": o nome é só a etiqueta, para você e para o compilador. Repare na diferença que as aspas fazem:
int idade = 29;
Console.WriteLine("idade");
Console.WriteLine(idade);
$ dotnet run nomevalor.cs idade « com aspas: o texto "idade" 29 « sem aspas: o valor da variável idade
Outros tipos
Cada tipo de informação tem o seu tipo de caixa. Estes seis bastam para o Nível 1:
string nome = "Ana";
int idade = 29;
double altura = 1.65;
decimal saldo = 150.75m;
bool cliente = true;
char inicial = 'A';
Console.WriteLine($"{nome} ({inicial}.) tem {idade} anos e {altura} m.");
Console.WriteLine($"Saldo: {saldo}. Cliente: {cliente}.");
$ dotnet run tipos.cs Ana (A.) tem 29 anos e 1,65 m. Saldo: 150,75. Cliente: True.
| Tipo | Guarda | Como se escreve o valor | Aula |
|---|---|---|---|
string | Um texto | Entre aspas duplas: "Ana" | Strings |
int | Um número inteiro | 29, -3, 0 | Inteiros |
double | Um número com casas decimais (medidas, contas científicas) | Com ponto: 1.65 | float, double e decimal |
decimal | Um número com casas decimais exatas: dinheiro | Com ponto e um m no fim: 150.75m | float, double e decimal |
bool | Verdadeiro ou falso | true ou false | char e bool |
char | Um caractere só | Entre aspas simples: 'A' | char e bool |
No código, as casas decimais são sempre separadas com ponto (1.65), como nos Estados Unidos. Na tela, o .NET usa o costume do país do computador: no Brasil, vírgula (1,65). O true aparece como True. A visão geral dos tipos está em Tipos de Dados.
Experimente: clique em Rodar e veja a frase. Depois troque o valor de quantidade para 8 e rode de novo. Se quiser ir além, crie string fruta = "peras"; e use {fruta} no lugar da palavra "maçãs".
int quantidade = 6;
Console.WriteLine($"A Ana comprou {quantidade} maçãs.");
int quantidade = 8;
Console.WriteLine($"A Ana comprou {quantidade} maçãs.");
2. Mudar o valor
Depois de declarada, a variável é usada só pelo nome, sem repetir o tipo. Para trocar o valor, escreva nome = novo valor;. Isso se chama atribuição, e o valor antigo é jogado fora:
int macas = 6;
Console.WriteLine($"Antes: {macas}");
macas = 4;
Console.WriteLine($"Depois: {macas}");
macas = macas + 2;
Console.WriteLine($"Mais duas: {macas}");
$ dotnet run mudar.cs Antes: 6 Depois: 4 Mais duas: 6
O programa roda de cima para baixo. A linha macas = macas + 2; parece estranha para quem lembra da matemática, mas lembre que = é "recebe":
- O C# calcula primeiro o lado direito: lê o valor atual de
macas(4) e soma 2, dando 6. - Depois guarda o resultado na caixa da esquerda, no lugar do 4.
Esse padrão tem um atalho, macas += 2;, explicado em Operadores de Atribuição. Com textos é igual:
string nome = "Ana";
Console.WriteLine($"Olá, {nome}!");
nome = "Bia";
Console.WriteLine($"Olá, {nome}!");
nome = nome + " Souza";
Console.WriteLine(nome);
$ dotnet run texto.cs Olá, Ana! Olá, Bia! Bia Souza
Declarar, inicializar, atribuir
Três palavras aparecem o tempo todo em livros e mensagens de erro:
| Palavra | O que é | Exemplo |
|---|---|---|
| declarar | criar a caixa (dizer tipo e nome) | int macas; |
| inicializar | dar o primeiro valor na mesma linha da declaração | int macas = 6; |
| atribuir | guardar um valor numa caixa que já existe | macas = 4; |
Copiar uma variável para outra
int b = a; copia o valor. Depois disso, as duas caixas são independentes:
int a = 1;
int b = a;
a = 5;
Console.WriteLine($"a={a} b={b}");
$ dotnet run copia.cs a=5 b=1 « mudar a depois não mexeu em b
(Isso vale para os tipos desta aula. Com objetos, no Nível 2, a cópia funciona de outro jeito; aula Valor × Referência.)
O tipo nunca muda
Uma caixa de int continua sendo de int até o fim. Tentar guardar um texto nela é recusado:
int idade = 29; idade = "trinta"; Console.WriteLine(idade);
$ dotnet run tipo.cs /home/ana/cs/variaveis/tipo.cs(2,9): error CS0029: Não é possível converter implicitamente tipo "string" em "int" Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
"Não é possível converter, sozinho, um texto (string) em número inteiro (int)". A coluna 9 aponta o "trinta". Em inglês: Cannot implicitly convert type 'string' to 'int'. E um número com casas decimais numa caixa de int? O C# também recusa, para não jogar fora o .9 sem você perceber:
int idade = 29; idade = 29.9; Console.WriteLine(idade);
$ dotnet run corta.cs /home/ana/cs/variaveis/corta.cs(2,9): error CS0266: Não é possível converter implicitamente tipo "double" em "int". Existe uma conversão explícita (há uma conversão ausente?) Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
- Não é possível converter implicitamente tipo "double" em "int"
- O
29.9é umdouble. Guardá-lo numintperderia a parte decimal, e o C# não faz isso escondido. - Existe uma conversão explícita
- "Mas existe um jeito de pedir": a conversão explícita, ou cast, que é escrever o tipo entre parênteses:
(int)29.9. - (há uma conversão ausente?)
- "Faltou um cast?". Em inglês, a mensagem toda é
Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?).
Com o cast, a decisão fica por sua conta, e escrita no código para todo mundo ver:
$ dotnet run cast.cs « int idade = (int)29.9; 29 « o .9 foi cortado (não arredondado)
Os detalhes estão em Conversão de Tipos. Para transformar um texto como "30" em número, o caminho é outro: Parse e TryParse.
3. Várias variáveis numa linha
Variáveis do mesmo tipo podem ser declaradas juntas, separadas por vírgula. Mas cuidado:
int a = 1, b = 2, c = 3;
Console.WriteLine($"{a} {b} {c}");
int x, y = 5;
Console.WriteLine($"{x} {y}");
$ dotnet run linha.cs /home/ana/cs/variaveis/linha.cs(4,22): error CS0165: Uso de variável local não atribuída "x" Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
A linha 1 está certa: três variáveis, cada uma com seu valor. A linha 3 é a armadilha: quem lê int x, y = 5; pode achar que as duas valem 5, mas o = 5 vale só para o y. O x ficou sem valor, e, na linha 4, coluna 22, a Ana tentou mostrá-lo. A seção 4 explica esse erro.
Declarar várias numa linha economiza espaço, mas esconde enganos como esse. As convenções do C# recomendam uma declaração por linha, cada uma com seu valor. Variáveis de tipos diferentes (um int e um string) nunca podem ir na mesma declaração.
4. Variável sem valor: o erro CS0165
O C# deixa você declarar uma variável sem valor (int pontos;) e dar o valor depois. O que ele não deixa é ler a variável antes de ela receber um valor:
int pontos;
pontos = pontos + 10;
Console.WriteLine($"Pontos: {pontos}");
$ dotnet run semvalor.cs /home/ana/cs/variaveis/semvalor.cs(2,10): error CS0165: Uso de variável local não atribuída "pontos" Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
- Uso de variável local
- Você usou (leu) a variável. Local quer dizer criada ali dentro do programa, e não num campo de uma classe (aula Campos).
- não atribuída
- Ela nunca recebeu um valor. A coluna 10 aponta o
pontosdo lado direito do=: para calcularpontos + 10, o C# precisaria saber quanto valepontosagora. - "pontos"
- O nome da variável. Em inglês:
Use of unassigned local variable 'pontos'.
Em linguagens mais antigas, como o C, esse programa compila e a variável vem com um valor qualquer, o "lixo" que estava na memória. O C# fecha essa porta: é um error, e o programa nem roda. O compilador confere, linha por linha, se toda variável lida já recebeu um valor antes. Ele confere até os caminhos de um if (aula if e else; por enquanto, leia como uma frase):
int compras = int.Parse(Console.ReadLine() ?? "0");
int desconto;
if (compras > 10)
{
desconto = 5;
}
else if (compras > 5)
{
desconto = 2;
}
int pagar = 100 - desconto;
Console.WriteLine($"Você paga: {pagar} reais");
$ echo 3 | dotnet run talvez.cs /home/ana/cs/variaveis/talvez.cs(11,19): error CS0165: Uso de variável local não atribuída "desconto" Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
(A linha 1 lê um número digitado; aula Parse e TryParse.) O desconto só recebe valor se a Ana fez mais de 5 compras. Com 5 ou menos, nenhum dos dois blocos roda, e a linha 11 leria uma caixa vazia. O compilador achou esse caminho sem nem rodar o programa, e não importa o número digitado: o programa não é gerado.
Sempre que puder, dê o valor já na declaração: int pontos = 0;, int desconto = 0;. Se ainda não souber o valor certo, comece com zero (ou "" para textos). O código fica mais claro e o CS0165 nunca aparece.
Missão: rode e leia o erro: qual variável está sem valor? Conserte só a linha da declaração dela, para o programa mostrar Pontos: 10.
int pontos;
int bonus = 10;
pontos = pontos + bonus;
Console.WriteLine($"Pontos: {pontos}");
int pontos = 0;
int bonus = 10;
pontos = pontos + bonus;
Console.WriteLine($"Pontos: {pontos}");
5. Antes de declarar, duas vezes, fora do bloco
O compilador lê o arquivo de cima para baixo. Uma variável só pode ser usada da linha da declaração para baixo:
Console.WriteLine(total); int total = 50;
$ dotnet run antes.cs /home/ana/cs/variaveis/antes.cs(1,19): error CS0841: Não é possível usar a variável local "total" antes de declará-la Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
A mensagem é clara: a total existe, mas só a partir da linha 2. Em inglês: Cannot use local variable 'total' before it is declared. Se o nome estivesse escrito errado (totla), o erro seria o CS0103: O nome "totla" não existe no contexto atual (aula Lendo Erros do Compilador).
E criar duas variáveis com o mesmo nome também é erro:
int total = 50; int total = 80; Console.WriteLine(total);
$ dotnet run dupla.cs /home/ana/cs/variaveis/dupla.cs(2,5): error CS0128: Uma variável de local ou função denominada 'total' já está definida neste escopo /home/ana/cs/variaveis/dupla.cs(2,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.
"Uma variável local chamada total já está definida neste escopo" (o escopo é a região do código onde um nome vale; aqui, o arquivo todo). Em inglês: A local variable or function named 'total' is already defined in this scope. O aviso CS0219 é consequência: a segunda total, que o compilador recusou, nunca é lida. Para mudar o valor, escreva sem o tipo: total = 80;. Repetir o int pede uma caixa nova com uma etiqueta que já existe.
Missão: este programa não compila. Rode, leia o erro e conserte a linha 2 para que ela só troque o valor de total. O programa deve mostrar Total: 80, sem avisos.
int total = 50;
int total = 80;
Console.WriteLine($"Total: {total}");
int total = 50;
total = 80;
Console.WriteLine($"Total: {total}");
Uma variável vive dentro do seu bloco
Uma variável criada dentro de um bloco { } só existe dentro dele. Depois da }, a etiqueta é jogada fora:
int idade = 20;
if (idade >= 18)
{
string mensagem = "Pode tirar a carteira.";
Console.WriteLine(mensagem);
}
Console.WriteLine(mensagem);
$ dotnet run bloco.cs /home/ana/cs/variaveis/bloco.cs(7,19): error CS0103: O nome "mensagem" não existe no contexto atual Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
Na linha 7, fora do bloco, a mensagem não existe mais. Se você precisa dela depois do bloco, declare-a antes, do lado de fora. O assunto completo é a aula Escopo.
6. Deixar o C# descobrir o tipo: var
Quando o valor deixa o tipo óbvio, você pode escrever var no lugar do tipo, e o compilador descobre sozinho:
var cidade = "Recife";
var habitantes = 1500000;
Console.WriteLine($"{cidade} tem {habitantes} habitantes.");
cidade = 42;
$ dotnet run var.cs /home/ana/cs/variaveis/var.cs(4,10): error CS0029: Não é possível converter implicitamente tipo "int" em "string" Ocorreu uma falha no build. Corrija os erros de build e execute novamente.
O var não cria uma caixa "de qualquer coisa": cidade virou string na linha 1, para sempre, e por isso o 42 da linha 4 foi recusado. O var é só um atalho para não escrever o tipo. Quando usar (e quando não) é assunto da aula Inferência com var; enquanto você aprende os tipos, o guia escreve o tipo por extenso.
Quando dá errado
error CS0165: Uso de variável local não atribuída "x"
O que significa: o programa lê uma variável que ainda não recebeu valor, ou que pode não ter recebido, em algum caminho (um if sem else). Também acontece com int x, y = 5;, em que só o y tem valor.
Como consertar: dê um valor na declaração: int x = 0;.
error CS0841: Não é possível usar a variável local "x" antes de declará-la
O que significa: a declaração está mais abaixo da linha que usa a variável.
Como consertar: mova a declaração para cima da primeira linha que usa a variável.
error CS0103: O nome "x" não existe no contexto atual
O que significa: o nome não existe ali: está escrito diferente (maiúscula, acento, letra trocada), ou a variável foi criada dentro de outro bloco { }, que já terminou.
Como consertar: copie o nome da mensagem e compare com a declaração. Se ela está num bloco, declare-a antes do bloco.
error CS0128: Uma variável de local ou função denominada 'x' já está definida neste escopo
O que significa: o mesmo nome foi declarado duas vezes.
Como consertar: para trocar o valor, tire o tipo da segunda linha (x = 80;). Se são duas coisas diferentes, dê nomes diferentes.
error CS0029 / CS0266 / CS0664: o valor não cabe no tipo
O que significa: o valor não é do tipo da variável: um texto num int (CS0029), um número com casas decimais num int (CS0266). Com dinheiro, há um parente, o CS0664, quando se esquece o m: decimal preco = 12.50; dá Literal do tipo double não pode ser convertido implicitamente no tipo "decimal"; use um sufixo "M" para criar um literal desse tipo (o 12.50 sem m é um double).
Como consertar: use um valor do tipo certo (29, 12.50m), ou mude o tipo da variável. Se a perda é de propósito, use o cast: (int)29.9. Em inglês, o CS0664 é Literal of type double cannot be implicitly converted to type 'decimal'; use an 'M' suffix to create a literal of this type.
warning CS0168 / CS0219: variável declarada (ou atribuída) e nunca usada
O que significa: a variável foi criada e ninguém leu o valor dela. Muitas vezes é um nome escrito errado na linha que deveria usá-la.
Como consertar: use a variável ou apague-a (aula Avisos do Compilador).
Referência rápida
| Escrita | O que faz |
|---|---|
int x = 10; | Declara x com valor inicial 10 |
string nome = "Ana"; | Uma variável de texto |
decimal preco = 12.50m; | Uma variável de dinheiro (com m) |
int x; | Declara sem valor: não pode ser lida até receber um (CS0165) |
x = 20; | Atribui: troca o valor (sem repetir o tipo) |
x = x + 1; | Calcula com o valor atual e guarda o resultado |
int b = a; | Copia o valor de a; as duas ficam independentes |
int a = 1, b = 2; | Várias do mesmo tipo numa linha (cada uma com seu valor) |
Console.WriteLine(x); | Mostra o valor |
Console.WriteLine($"x vale {x}"); | Mostra o valor no meio de um texto |
(int)29.9 | Converte de propósito (cast): dá 29 |
var cidade = "Recife"; | O compilador descobre o tipo (string) |
Exercícios
1. Declarar
Complete para criar uma variável inteira alunos valendo 32:
2. Texto
Complete o tipo da variável que guarda o nome da escola:
3. Mostrar
Complete para mostrar Turma com 32 alunos, usando a variável alunos:
4. Depois de int x, y = 5;, o que acontece com Console.WriteLine(x);?
5. O que o programa mostra? int a = 2; int b = a; a = 7; Console.WriteLine(b);
6. O que acontece com int nota = 7.8;?
7. A linha 2 tem int total = 80; e a linha 1 já tinha int total = 50;. O que o compilador diz?
Missão final: o caixa da lojinha
Missão: a Ana vendeu 3 cadernos a 5.50m cada. Declare quantidade (int, valendo 3) e preco (decimal, valendo 5.50m), calcule total (decimal) como quantidade * preco (o * é "vezes") e mostre a primeira linha. Depois a cliente pegou mais um caderno: mude quantidade para 4 (sem declarar de novo), calcule o total outra vez e mostre a segunda linha. Sem avisos.
Total: 16,50 reais Total: 22,00 reais
// declare quantidade, preco e total aqui // mostre o total // mude a quantidade, recalcule e mostre de novo
int quantidade = 3;
decimal preco = 5.50m;
decimal total = quantidade * preco;
Console.WriteLine($"Total: {total} reais");
quantidade = 4;
total = quantidade * preco;
Console.WriteLine($"Total: {total} reais");
Repare que o total não muda sozinho quando a quantidade muda: a conta quantidade * preco é feita na hora em que a linha roda, e o resultado é guardado. Por isso a missão pede para calcular de novo. E o decimal guardou as duas casas do dinheiro: 22,00, e não 22.
Resumo
- Variável = caixa com tipo (formato), nome (etiqueta) e valor. Declare com
tipo nome = valor;. - Os tipos do começo:
string(texto),int(inteiro),double(decimal),decimal(dinheiro, comm),bool(true/false) echar(um caractere). - Mostre com
Console.WriteLine(x)ou, no meio de um texto, com$"… {x} …". - Para mudar o valor:
nome = novo;, sem repetir o tipo. O lado direito é calculado primeiro. Copiar (b = a) cria uma cópia independente. - O tipo nunca muda: texto num
intdáCS0029;29.9numintdáCS0266(use(int)se quiser cortar de propósito). - Em
int x, y = 5;, só oyvale 5. Prefira uma declaração por linha. - O C# não deixa ler uma variável sem valor (
CS0165), nem em algum caminho de umif. Regra: toda variável nasce com valor. - A variável só existe da declaração para baixo (
CS0841) e dentro do seu bloco (CS0103), e o mesmo nome não pode ser declarado duas vezes (CS0128).