C#: Variáveis e tipos de dados

Pense em uma variável como uma caixa rotulada: a etiqueta é o nome, e a caixa contém os dados. Escolher o tamanho e o tipo certos de caixa mantém seus dados seguros e garante a eficiência.

1. Declaração e inicialização de variáveis

C# é uma linguagem fortemente tipada; portanto, é necessário especificar um tipo ao declarar uma variável (ou usar var para que o compilador o infira):

CSHARP
int age;
age = 25;

string name = "Alice";
double score = 95.5;

Você também pode declarar várias variáveis do mesmo tipo em uma única linha:

CSHARP
int x = 1, y = 2, z = 3;

Aviso: o C# não permite o uso de variáveis locais não inicializadas; o compilador gerará um erro.


2. Regras de nomenclatura

O C# impõe regras rígidas para a nomenclatura de variáveis:

(1) camelCase e PascalCase

O C# possui duas convenções de nomenclatura principais:

Tipo de identificador Estilo Exemplos
Variáveis locais, campos camelCase studentName, totalCount
Métodos, classes, propriedades PascalCase CalculateSum, Student

Dica: camelCase: a primeira palavra em minúscula, as palavras seguintes com a primeira letra maiúscula; PascalCase: todas as palavras com a primeira letra maiúscula.

CSHARP
int studentAge = 18;
double averageScore = 87.5;
string homeAddress = "Beijing";

3. Tipos de inteiros

O C# oferece 8 tipos de inteiros, abrangendo tanto os assinados quanto os não assinados:

Tipo Bytes Intervalo Sufixo
sbyte 1 -128 ~ 127
byte 1 0 ~ 255
short 2 -32.768 ~ 32.767
ushort 2 0 ~ 65.535
int 4 -2.147.483.648 ~ 2.147.483.647
uint 4 0 ~ 4.294.967.295 U
long 8 -9.223.372.036.854.775.808 ~ 9.223.372.036.854.775.807 L
ulong 8 0 ~ 18.446.744.073.709.551.615 UL

Dica: Ao contrário do Java, o C# possui tipos de inteiros sem sinal (byte, ushort, uint, ulong). Observe que o byte do C# é sem sinal, enquanto a versão com sinal é sbyte.

▶ Exemplo

CSHARP
sbyte sb = -100;
byte b = 200;
short s = -30000;
ushort us = 60000;
int i = 100000;
uint ui = 3000000000U;
long l = 9000000000000000000L;
ulong ul = 18000000000000000000UL;

Console.WriteLine($"sbyte:  {sb}");
Console.WriteLine($"byte:   {b}");
Console.WriteLine($"short:  {s}");
Console.WriteLine($"ushort: {us}");
Console.WriteLine($"int:    {i}");
Console.WriteLine($"uint:   {ui}");
Console.WriteLine($"long:   {l}");
Console.WriteLine($"ulong:  {ul}");
▶ Experimente
TEXT 📖 Somente leitura
sbyte:  -100
byte:   200
short:  -30000
ushort: 60000
int:    100000
uint:   3000000000
long:   9000000000000000000
ulong:  18000000000000000000

4. Tipos de ponto flutuante

Tipo Bytes Precisão Intervalo (aprox.) Sufixo Caso de uso
float 4 7 dígitos +/-1,5×10⁻⁴⁵ ~ +/-3,4×10³⁸ f Gráficos, jogos
double 8 15-16 dígitos +/-5,0×10⁻³²⁴ ~ +/-1,7×10³⁰⁸ d (padrão) Computação científica
decimal 16 28-29 dígitos +/-1,0×10⁻²⁸ ~ +/-7,9×10²⁸ m Valores financeiros

Aviso: Os literais decimais são double por padrão. É necessário adicionar um sufixo ao atribuir valores a float ou decimal; caso contrário, o compilador gerará um erro.

CSHARP
float f = 3.14f;
double d = 3.14;
decimal m = 3.14m;

Console.WriteLine($"float:   {f}");
Console.WriteLine($"double:  {d}");
Console.WriteLine($"decimal: {m}");
TEXT 📖 Somente leitura
float:   3.14
double:  3.14
decimal: 3.14

Dica: decimal foi projetado para cálculos financeiros e evita erros de ponto flutuante binário. Por exemplo, 0.1 + 0.2 não é exatamente igual a 0.3 quando comparado a double, mas é exatamente igual a decimal.


5. Tipo bool

bool possui apenas dois valores: true e false, ocupando 1 byte.

Aviso: Ao contrário do C, o bool do C# não pode ser convertido implicitamente para ou a partir de inteiros. if(1) é inválido; você deve escrever if(true) ou if(x != 0).

CSHARP
bool isReady = true;
bool isEmpty = false;

Console.WriteLine($"isReady:  {isReady}");
Console.WriteLine($"isEmpty:  {isEmpty}");
TEXT 📖 Somente leitura
isReady:  True
isEmpty:  False

6. Tipo char

O char do C# é um caractere Unicode de 2 bytes, e não um caractere ASCII de 1 byte como no C.

CSHARP
char ch1 = 'A';
char ch2 = '\u03a9';

Console.WriteLine($"ch1: {ch1}");
Console.WriteLine($"ch2: {ch2}");
Console.WriteLine($"ch1 code: {(int)ch1}");
Console.WriteLine($"ch2 code: {(int)ch2}");
TEXT 📖 Somente leitura
ch1: A
ch2: Ω
ch1 code: 65
ch2 code: 937

Dica: char usa aspas simples 'A', enquanto string usa aspas duplas "A" — são tipos completamente diferentes.


7. Tipo string

string é um tipo de referência que representa uma sequência imutável de caracteres Unicode.

CSHARP
string greeting = "Hello";
string name = "World";
string message = greeting + ", " + name + "!";

Console.WriteLine(message);
Console.WriteLine($"Length: {message.Length}");
TEXT 📖 Somente leitura
Hello, World!
Length: 13

Aviso: string é um tipo de referência, e seu valor padrão é null (não uma string vazia ""). Acessar uma string null resultará em uma exceção NullReferenceException.


8. Tipo implícito em var

O C# 3.0 introduziu a palavra-chave var, que permite que o compilador infira o tipo a partir do valor inicial:

CSHARP
var count = 42;
var price = 9.99m;
var label = "hello";
var flag = true;

Console.WriteLine(count.GetType().Name);
Console.WriteLine(price.GetType().Name);
Console.WriteLine(label.GetType().Name);
Console.WriteLine(flag.GetType().Name);
TEXT 📖 Somente leitura
Int32
Decimal
String
Boolean

Atenção: var não significa “qualquer tipo” — o tipo da variável é determinado em tempo de compilação e deve ser inicializado. O seguinte é inválido:

CSHARP
var x;
var x = null;

Dica: Use var quando os nomes dos tipos forem longos ou quando o tipo for óbvio pelo contexto. Evite usá-lo em excesso, pois isso pode reduzir a legibilidade.


9. sizeof — Verificação do tamanho do tipo

sizeof retorna o número de bytes que um tipo ocupa. Pode ser usada diretamente para tipos primitivos; outros tipos exigem um contexto unsafe.

▶ Exemplo

CSHARP
Console.WriteLine($"sbyte:    {sizeof(sbyte)} bytes");
Console.WriteLine($"byte:     {sizeof(byte)} bytes");
Console.WriteLine($"short:    {sizeof(short)} bytes");
Console.WriteLine($"ushort:   {sizeof(ushort)} bytes");
Console.WriteLine($"int:      {sizeof(int)} bytes");
Console.WriteLine($"uint:     {sizeof(uint)} bytes");
Console.WriteLine($"long:     {sizeof(long)} bytes");
Console.WriteLine($"ulong:    {sizeof(ulong)} bytes");
Console.WriteLine($"float:    {sizeof(float)} bytes");
Console.WriteLine($"double:   {sizeof(double)} bytes");
Console.WriteLine($"decimal:  {sizeof(decimal)} bytes");
Console.WriteLine($"char:     {sizeof(char)} bytes");
Console.WriteLine($"bool:     {sizeof(bool)} bytes");
▶ Experimente
TEXT 📖 Somente leitura
sbyte:    1 bytes
byte:     1 bytes
short:    2 bytes
ushort:   2 bytes
int:      4 bytes
uint:     4 bytes
long:     8 bytes
ulong:    8 bytes
float:    4 bytes
double:   8 bytes
decimal:  16 bytes
char:     2 bytes
bool:     1 bytes

10. const Constantes

Use const para declarar constantes em tempo de compilação cujos valores não podem ser alterados. Elas devem ser inicializadas no momento da declaração:

CSHARP
const double Pi = 3.14159265358979;
const int MaxRetry = 3;
const string AppName = "MyApp";

Console.WriteLine($"Pi = {Pi}");
Console.WriteLine($"MaxRetry = {MaxRetry}");
Console.WriteLine($"AppName = {AppName}");
TEXT 📖 Somente leitura
Pi = 3.14159265358979
MaxRetry = 3
AppName = MyApp

Aviso: os nomes const geralmente utilizam o formato PascalCase. O valor deve ser determinável em tempo de compilação e não pode ser uma variável nem o resultado de uma chamada de método.

Dica: Se você precisar de uma “constante” determinada em tempo de execução, use um campo readonly em vez disso.


11. Valores padrão de tipos

Cada tipo possui um valor padrão quando nenhum valor inicial é atribuído:

Tipo Valor padrão
sbyte / byte / short / ushort / int / uint / long / ulong 0
float 0.0f
double 0.0d
decimal 0.0m
char '\0'
bool false
string null
Qualquer tipo de referência null

▶ Exemplo

CSHARP
int defaultInt = default;
bool defaultBool = default;
char defaultChar = default;
string defaultString = default;
double defaultDouble = default;

Console.WriteLine($"int:    [{defaultInt}]");
Console.WriteLine($"bool:   [{defaultBool}]");
Console.WriteLine($"char:   [{(int)defaultChar}]");
Console.WriteLine($"string: [{defaultString}]");
Console.WriteLine($"double: [{defaultDouble}]");
▶ Experimente
TEXT 📖 Somente leitura
int:    [0]
bool:   [False]
char:   [0]
string: []
double: [0]

Dica: A palavra-chave default permite obter o valor padrão de qualquer tipo e é especialmente comum em genéricos: default(T).


12. Tipos de valor x tipos de referência — Introdução

Os tipos do C# se enquadram em duas grandes categorias:

Categoria Armazenamento Comportamento de atribuição Tipos típicos
Tipo de valor Pilha (normalmente) Copia o valor int, bool, char, decimal, struct, enum
Tipo de referência Heap Copia a referência (endereço) string, class, object, matrizes
CSHARP
int a = 10;
int b = a;
b = 20;
Console.WriteLine($"a = {a}, b = {b}");

string s1 = "hello";
string s2 = s1;
s2 = "world";
Console.WriteLine($"s1 = {s1}, s2 = {s2}");
TEXT 📖 Somente leitura
a = 10, b = 20
s1 = hello, s2 = world

Aviso: s1 não se tornou "world" porque string é imutável — s2 = "world" não modifica o objeto original, mas faz com que s2 aponte para um novo. A atribuição de tipos de valor copia o valor real, enquanto a atribuição de tipos de referência copia a referência. No entanto, a imutabilidade de string faz com que ele se comporte como um tipo de valor.

❓ Perguntas Frequentes

P: Qual é a diferença entre var e dynamic? R: var determina o tipo em tempo de compilação e é seguro em termos de tipos; dynamic determina o tipo em tempo de execução, não possui verificação de tipo em tempo de compilação, apresenta desempenho inferior e é mais propenso a erros.

P: Por que decimal é melhor do que double para cálculos monetários? R: decimal utiliza armazenamento decimal, de modo que 0.1 pode ser representado com exatidão; double usa armazenamento binário, no qual 0.1 não pode ser representado com exatidão, o que leva a erros cumulativos de arredondamento.

P: string é um tipo de valor ou um tipo de referência? R: string é um tipo de referência, mas, devido à sua imutabilidade, a atribuição apresenta semântica de valor — a modificação de uma variável não afeta a outra.

P: Qual é a diferença entre const e readonly? R: const é uma constante de tempo de compilação que deve ser atribuída na declaração e é implicitamente estática; readonly é uma constante de tempo de execução que pode ser atribuída em um construtor e pode variar de instância para instância.

📖 Resumo

📝 Exercícios

  1. Declare uma variável int chamada age com o valor da sua idade e uma variável string chamada name com o valor do seu nome; em seguida, exiba ambas
  2. Calcule 0.1 + 0.2 utilizando float, double e decimal, respectivamente, e verifique se os resultados são exatamente iguais a 0.3
  3. Use sizeof para imprimir os tamanhos em bytes de int, double, char e bool
  4. Declare uma variável const double Pi = 3.14159265 e calcule a área de um círculo de raio 5; em seguida, exiba o resultado
  5. Use a palavra-chave default para obter e exibir os valores padrão de int, bool, char e string
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%