C#: Classes e objetos
1. Por que as classes são necessárias
C# é uma linguagem orientada a objetos na qual quase tudo é um objeto. Anteriormente, escrevemos código usando instruções de nível superior, mas os programas reais em C# são construídos a partir de classes. Uma classe é um modelo para objetos — ela define dados (campos) e comportamento (métodos), enquanto um objeto é uma instância concreta de uma classe.
2. Definição de classe
Use a palavra-chave class para definir uma classe. Os nomes das classes devem seguir a convenção PascalCase (colocar em maiúscula a primeira letra de cada palavra).
class Person
{
public string Name;
public int Age;
public void SayHello()
{
System.Console.WriteLine($"Hello, I'm {Name}, {Age} years old.");
}
}
publicsignifica que o membro pode ser acessado de foraName,Agesão campos (armazenam dados)SayHelloé um método (define um comportamento)
3. Criação de objetos
Use a palavra-chave new para criar um objeto a partir de uma classe:
Person p = new Person();
p.Name = "Tom";
p.Age = 18;
p.SayHello();
Hello, I'm Tom, 18 years old.
Cada new cria um objeto independente com sua própria cópia dos campos.
4. Campos e inicialização de campos
É possível atribuir valores iniciais aos campos na declaração:
class Student
{
public string Name = "Unknown";
public int Score = 0;
}
Se nenhum valor inicial for atribuído, os tipos numéricos assumem por padrão o valor 0, e os tipos de referência assumem por padrão o valor null.
Os modificadores de acesso controlam a visibilidade dos campos:
| Modificador | Significado |
|---|---|
public |
Acessível de qualquer lugar |
private |
Acessível apenas dentro da classe (padrão) |
Normalmente, os campos são definidos como private e o acesso é controlado por meio de métodos ou propriedades.
▶ Exemplo
using System;
class BankAccount
{
private decimal balance = 1000m;
public void Deposit(decimal amount)
{
balance += amount;
Console.WriteLine($"Deposited {amount}, balance is {balance}");
}
public void ShowBalance()
{
Console.WriteLine($"Current balance: {balance}");
}
}
class Program
{
static void Main()
{
BankAccount acc = new BankAccount();
acc.ShowBalance();
acc.Deposit(500m);
}
}
Current balance: 1000
Deposited 500, balance is 1500
5. Métodos
Métodos são funções definidas dentro de uma classe que descrevem o comportamento de um objeto. Os métodos podem acessar campos dentro da mesma classe:
class Calculator
{
private int result = 0;
public void Add(int value)
{
result += value;
}
public int GetResult()
{
return result;
}
}
6. A palavra-chave “this”
this refere-se à instância atual do objeto. Seu uso mais comum é distinguir campos de parâmetros com o mesmo nome:
class Person
{
public string Name;
public int Age;
public Person(string Name, int Age)
{
this.Name = Name;
this.Age = Age;
}
}
this.Namerefere-se ao campo,Namerefere-se ao parâmetrothispode ser omitido quando não houver ambiguidade
7. Construtores
Os construtores são chamados automaticamente quando um objeto é criado e servem para inicializar o objeto.
(1) Construtor sem parâmetros
Se nenhum construtor for definido, o compilador gera automaticamente um construtor sem parâmetros:
class Dog
{
public string Name;
public Dog()
{
Name = "Unnamed";
}
}
(2) Construtor parametrizado
class Dog
{
public string Name;
public Dog(string name)
{
Name = name;
}
}
⚠️ Depois que você definir qualquer construtor, o compilador não irá mais gerar automaticamente um construtor sem parâmetros.
(3) Sobrecarga de construtores
É possível definir vários construtores com parâmetros diferentes:
class Dog
{
public string Name;
public int Age;
public Dog()
{
Name = "Unnamed";
Age = 0;
}
public Dog(string name)
{
Name = name;
Age = 0;
}
public Dog(string name, int age)
{
Name = name;
Age = age;
}
}
(4) Encadeamento de construtores
Use this(...) para que um construtor chame outro, evitando a duplicação de código:
class Dog
{
public string Name;
public int Age;
public Dog() : this("Unnamed", 0) { }
public Dog(string name) : this(name, 0) { }
public Dog(string name, int age)
{
Name = name;
Age = age;
}
}
▶ Exemplo
using System;
class Book
{
public string Title;
public string Author;
public decimal Price;
public Book() : this("Unknown", "Unknown", 0m) { }
public Book(string title, string author) : this(title, author, 29.9m) { }
public Book(string title, string author, decimal price)
{
Title = title;
Author = author;
Price = price;
}
public void PrintInfo()
{
Console.WriteLine($"\"{Title}\" Author: {Author} Price: {Price}");
}
}
class Program
{
static void Main()
{
Book b1 = new Book();
Book b2 = new Book("C# Basics", "Alice");
Book b3 = new Book("Advanced C#", "Bob", 59.9m);
b1.PrintInfo();
b2.PrintInfo();
b3.PrintInfo();
}
}
"Unknown" Author: Unknown Price: 0
"C# Basics" Author: Alice Price: 29.9
"Advanced C#" Author: Bob Price: 59.9
8. Destruidores
Um destrutor é chamado antes de um objeto ser recolhido pelo coletor de lixo. A sintaxe é ~ClassName():
class Resource
{
~Resource()
{
Console.WriteLine("Object is being reclaimed");
}
}
📌 O C# possui coleta automática de lixo (GC), portanto, raramente é necessário escrever um destrutor manualmente. Os destrutores são usados apenas para liberar recursos não gerenciados (como identificadores de arquivos e conexões com bancos de dados), o que será discutido em detalhes em lições posteriores.
9. Inicializadores de objetos
O C# 3.0 introduziu a sintaxe de inicialização de objetos, que permite atribuir valores diretamente a campos ou propriedades públicas ao usar new:
Person p = new Person { Name = "Lily", Age = 20 };
Isso equivale a:
Person p = new Person();
p.Name = "Lily";
p.Age = 20;
Os inicializadores de objetos podem ser combinados com construtores parametrizados:
Person p = new Person("Lily") { Age = 20 };
▶ Exemplo
using System;
class Rectangle
{
public double Width = 1;
public double Height = 1;
public double Area()
{
return Width * Height;
}
}
class Program
{
static void Main()
{
Rectangle r1 = new Rectangle();
Rectangle r2 = new Rectangle { Width = 5, Height = 3 };
Rectangle r3 = new Rectangle { Width = 10 };
Console.WriteLine($"r1 area: {r1.Area()}");
Console.WriteLine($"r2 area: {r2.Area()}");
Console.WriteLine($"r3 area: {r3.Area()}");
}
}
r1 area: 1
r2 area: 15
r3 area: 10
10. Diferença entre “new” e “null”
| Conceito | Significado |
|---|---|
new ClassName() |
Cria um objeto na pilha e retorna uma referência a esse objeto |
null |
Não aponta para nenhum objeto; é o valor padrão para tipos de referência |
Person p1 = new Person();
Person p2 = null;
Console.WriteLine(p1 == null);
Console.WriteLine(p2 == null);
False
True
⚠️ Acessar um membro em uma referência null gera um NullReferenceException, o erro de tempo de execução mais comum em C#:
Person p = null;
p.SayHello();
💡 Verifique se há null antes de acessar:
if (p != null)
{
p.SayHello();
}
❓ Perguntas Frequentes
P: O que acontece se eu não definir um construtor? R: O compilador gera automaticamente um construtor sem parâmetros que atribui valores padrão aos campos.
P: Ainda é possível criar um objeto sem parâmetros depois de definir um construtor parametrizado? R: Não, a menos que você defina manualmente um construtor sem parâmetros também.
P: Isso pode ser usado em métodos estáticos? R: Não, isso se refere à instância atual, e os métodos estáticos não estão associados a uma instância.
P: Os inicializadores de objetos podem atribuir valores a campos privados? R: Não, eles só podem inicializar membros acessíveis (campos ou propriedades públicos).
P: “null” e 0 são a mesma coisa? R: Não. “null” significa “sem referência”, enquanto 0 é um valor de tipos numéricos. Tipos de valor não podem ser “null”.
📖 Resumo
- Uma classe é um modelo para objetos, definido com
class - Os objetos são criados com
new; cada objeto possui sua própria cópia dos campos - Os campos armazenam dados, os métodos definem o comportamento,
public/privatecontrolam o acesso thisrefere-se à instância atual, comumente usada para distinguir campos de parâmetros com o mesmo nome- Os construtores são chamados automaticamente ao criar um objeto, podem ser sobrecarregados e podem usar
this(...)para encadeamento - Os destrutores são chamados automaticamente pelo GC; geralmente, não é necessário escrevê-los manualmente
- Os inicializadores de objetos
new T { Field = value }simplificam a atribuição newcria um objeto;nullsignifica que não há referência a nenhum objeto; acessar membros nulos gera um erro
📝 Exercícios
- Defina uma classe
Carcom os camposBrand(string) eSpeed(int), um métodoAccelerate(int amount)que aumenta Speed e um construtor sem parâmetros que inicializa Speed como 0 - Adicione um construtor parametrizado
Car(string brand)à classeCare usethis(...)para implementar o encadeamento de construtores - Use um inicializador de objeto para criar um objeto
Care definir Brand e Speed; em seguida, chame o método Accelerate e exiba o valor final de Speed - Escreva um código que demonstre o seguinte: crie uma referência
Caratribuída anull, tente acessar seu membro, use try-catch para capturar oNullReferenceExceptione imprima uma mensagem