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.

Você vai aprender
  • O que é uma variável e como criar uma: int idade = 29;.
  • Como mostrar o valor com Console.WriteLine e com $"…{idade}…".
  • Os tipos mais usados no começo: int, double, decimal, string, bool e char.
  • 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 caixaNome técnicoExemplo
O formato (o que cabe nela)tipoint (número inteiro), string (texto)
A etiquetanomeidade, nome, preco
O que está guardado agoravalor29, "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. int vem 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.
TipoGuardaComo se escreve o valorAula
stringUm textoEntre aspas duplas: "Ana"Strings
intUm número inteiro29, -3, 0Inteiros
doubleUm número com casas decimais (medidas, contas científicas)Com ponto: 1.65float, double e decimal
decimalUm número com casas decimais exatas: dinheiroCom ponto e um m no fim: 150.75mfloat, double e decimal
boolVerdadeiro ou falsotrue ou falsechar e bool
charUm 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":

  1. O C# calcula primeiro o lado direito: lê o valor atual de macas (4) e soma 2, dando 6.
  2. 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:

PalavraO que éExemplo
declararcriar a caixa (dizer tipo e nome)int macas;
inicializardar o primeiro valor na mesma linha da declaraçãoint macas = 6;
atribuirguardar um valor numa caixa que já existemacas = 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 é um double. Guardá-lo num int perderia 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.

Uma variável por linha

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 pontos do lado direito do =: para calcular pontos + 10, o C# precisaria saber quanto vale pontos agora.
"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.

Regra do guia: toda variável nasce com valor

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

EscritaO 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.9Converte 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:

alunos = 32;

2. Texto

Complete o tipo da variável que guarda o nome da escola:

escola = "Escola da Vila";

3. Mostrar

Complete para mostrar Turma com 32 alunos, usando a variável alunos:

Console.WriteLine($"Turma com 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, com m), bool (true/false) e char (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 int dá CS0029; 29.9 num int dá CS0266 (use (int) se quiser cortar de propósito).
  • Em int x, y = 5;, só o y vale 5. Prefira uma declaração por linha.
  • O C# não deixa ler uma variável sem valor (CS0165), nem em algum caminho de um if. 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).