UC00620

Programação em C#

.NET, OOP, LINQ, Entity Framework

Curso profissional · 50h · Linguagem Microsoft

Plano

  1. Setup .NET
  2. Sintaxe C#
  3. OOP em C#
  4. Colecções e LINQ
  5. Excepções
  6. Ficheiros e I/O
  7. Entity Framework (BD)
  8. Projecto final

Bloco 1 · .NET

O que é C# e .NET

  • C#: linguagem da Microsoft (criada 2002).
  • .NET: plataforma multi-linguagem (C#, F#, VB.NET).
  • .NET 8+ (LTS): cross-platform (Windows/Linux/Mac).
  • Usado em: backend (ASP.NET), Unity (jogos), apps Windows.

Sintaxe parecida com Java e C++.

Setup

# Instalar .NET SDK 8 (LTS)
# https://dotnet.microsoft.com/download

dotnet --version
# 8.0.x

# Criar projecto
dotnet new console -n MinhaApp
cd MinhaApp
dotnet run

IDE: Visual Studio (Windows), Rider (multi), VSCode.

Hello World

// Program.cs (estilo moderno, top-level statements)
Console.WriteLine("Olá mundo!");

string nome = "Ana";
Console.WriteLine($"Olá, {nome}");
dotnet run

Top-level statements (.NET 6+): sem class Program { static void Main }.

Bloco 2 · Sintaxe

Tipos

int idade = 25;
long populacao = 8_000_000_000L;
double preco = 9.99;
decimal valor = 100.50m;  // financeiro
bool activo = true;
char letra = 'A';
string nome = "Ana";

// var (inferência)
var x = 42;          // int
var nome2 = "Ana";   // string

// Nullable
int? idade2 = null;
string? nome3 = null;

Operadores e strings

// Aritméticos: + - * / %
int soma = 5 + 3;
double real = 10.0 / 3;  // 3.333

// Interpolação (preferido)
string saudacao = $"Olá, {nome}, tens {idade} anos";

// Concatenação
string s = "Olá " + nome;

// Métodos
nome.ToUpper();
nome.Length;
nome.Substring(0, 3);
nome.Contains("a");
nome.Replace("a", "e");

Estruturas controlo

// If
if (idade >= 18) {
    Console.WriteLine("Adulto");
} else {
    Console.WriteLine("Menor");
}

// Switch expression (moderno)
string tipo = dia switch {
    1 or 2 or 3 or 4 or 5 => "Útil",
    6 or 7 => "Weekend",
    _ => "Inválido"
};

// Pattern matching
if (obj is string s && s.Length > 5) {
    Console.WriteLine(s);
}

Loops

// For
for (int i = 0; i < 10; i++) {
    Console.WriteLine(i);
}

// Foreach
string[] frutas = { "maçã", "uva", "pera" };
foreach (var f in frutas) {
    Console.WriteLine(f);
}

// While / do-while
int x = 0;
while (x < 5) { x++; }

Bloco 3 · OOP

Classe

public class Pessoa
{
    // Propriedade auto (get/set)
    public string Nome { get; set; }
    public int Idade { get; set; }
    
    // Construtor
    public Pessoa(string nome, int idade)
    {
        Nome = nome;
        Idade = idade;
    }
    
    // Método
    public void Apresentar()
    {
        Console.WriteLine($"Olá, sou {Nome}");
    }
}

// Uso
var p = new Pessoa("Ana", 25);
p.Apresentar();

Propriedades vs campos

public class Conta
{
    // Campo privado
    private double _saldo;
    
    // Propriedade com lógica
    public double Saldo
    {
        get { return _saldo; }
        set 
        { 
            if (value < 0) throw new ArgumentException("Negativo");
            _saldo = value;
        }
    }
    
    // Propriedade auto (compilador cria campo)
    public string Titular { get; set; }
    
    // Read-only
    public DateTime Criada { get; }
}

Herança

public class Empregado : Pessoa
{
    public double Salario { get; set; }
    
    public Empregado(string nome, int idade, double salario)
        : base(nome, idade)  // chama construtor pai
    {
        Salario = salario;
    }
    
    public override void Apresentar()
    {
        base.Apresentar();
        Console.WriteLine($"Salário: {Salario}€");
    }
}

virtual / override para polimorfismo.

Interfaces

public interface IAnimal
{
    void EmitirSom();
    string Nome { get; set; }
}

public class Cao : IAnimal
{
    public string Nome { get; set; }
    
    public void EmitirSom() {
        Console.WriteLine("Au au!");
    }
}

Convenção: nomes de interfaces começam com I.

Records (C# 9+)

// Imutável, value-based equality, ToString automático
public record Ponto(double X, double Y);

var p1 = new Ponto(1, 2);
var p2 = new Ponto(1, 2);
Console.WriteLine(p1 == p2);  // true (value equality!)
Console.WriteLine(p1);        // Ponto { X = 1, Y = 2 }

// With expression (cópia com modificação)
var p3 = p1 with { Y = 5 };

Bloco 4 · Colecções e LINQ

List, Dictionary, HashSet

using System.Collections.Generic;

// List
var nomes = new List<string> { "Ana", "Bruno" };
nomes.Add("Carla");
nomes.Remove("Ana");
Console.WriteLine(nomes.Count);

// Dictionary
var idades = new Dictionary<string, int> {
    ["Ana"] = 25,
    ["Bruno"] = 30
};
Console.WriteLine(idades["Ana"]);

// HashSet (sem duplicados)
var unicos = new HashSet<int> { 1, 2, 3, 1 };
// {1, 2, 3}

LINQ — Language Integrated Query

using System.Linq;

var numeros = new List<int> { 1, 2, 3, 4, 5, 6 };

// Method syntax (preferido)
var pares = numeros.Where(n => n % 2 == 0).ToList();
var dobrados = numeros.Select(n => n * 2).ToList();
var soma = numeros.Sum();
var max = numeros.Max();

// Query syntax (alternativa SQL-like)
var resultado = from n in numeros
                where n > 2
                orderby n descending
                select n * 2;

LINQ avançado

var produtos = new List<Produto> { ... };

// Filter + Map + GroupBy
var caros = produtos
    .Where(p => p.Preco > 100)
    .OrderByDescending(p => p.Preco)
    .Take(5)
    .Select(p => new { p.Nome, p.Preco })
    .ToList();

// Agrupar
var porCategoria = produtos
    .GroupBy(p => p.Categoria)
    .Select(g => new { 
        Categoria = g.Key, 
        Total = g.Sum(p => p.Preco) 
    });

Bloco 5 · Excepções

Try-catch

try
{
    int[] arr = { 1, 2, 3 };
    Console.WriteLine(arr[10]);
}
catch (IndexOutOfRangeException ex)
{
    Console.WriteLine($"Erro: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Outro: {ex.Message}");
}
finally
{
    Console.WriteLine("Sempre executa");
}

Throw e custom

public void Sacar(double valor)
{
    if (valor <= 0)
        throw new ArgumentException("Valor inválido", nameof(valor));
    
    if (valor > _saldo)
        throw new SaldoInsuficienteException($"Saldo: {_saldo}");
    
    _saldo -= valor;
}

public class SaldoInsuficienteException : Exception
{
    public SaldoInsuficienteException(string message) 
        : base(message) { }
}

Bloco 6 · Ficheiros

Ler e escrever

using System.IO;

// Ler tudo
string conteudo = File.ReadAllText("dados.txt");

// Ler linhas
string[] linhas = File.ReadAllLines("dados.txt");
foreach (var l in linhas) Console.WriteLine(l);

// Escrever (substitui)
File.WriteAllText("output.txt", "Olá mundo");

// Escrever linhas
File.WriteAllLines("output.txt", new[] { "linha 1", "linha 2" });

// Append
File.AppendAllText("log.txt", "Nova entrada\n");

// Existe?
bool existe = File.Exists("dados.txt");

JSON

using System.Text.Json;

// Serializar
var pessoa = new Pessoa("Ana", 25);
string json = JsonSerializer.Serialize(pessoa);
File.WriteAllText("pessoa.json", json);

// Desserializar
string lido = File.ReadAllText("pessoa.json");
var p = JsonSerializer.Deserialize<Pessoa>(lido);

// Indented
var opts = new JsonSerializerOptions { WriteIndented = true };
string jsonBonito = JsonSerializer.Serialize(pessoa, opts);

Bloco 7 · Entity Framework

Setup EF Core

dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet tool install --global dotnet-ef

Modelo + DbContext

public class Produto
{
    public int Id { get; set; }
    public string Nome { get; set; } = "";
    public double Preco { get; set; }
}

public class AppDbContext : DbContext
{
    public DbSet<Produto> Produtos { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder o)
    {
        o.UseSqlite("Data Source=loja.db");
    }
}

Migrations e CRUD

dotnet ef migrations add InicialDB
dotnet ef database update
using var db = new AppDbContext();

// Create
db.Produtos.Add(new Produto { Nome = "Caneta", Preco = 1.50 });
db.SaveChanges();

// Read
var todos = db.Produtos.ToList();
var caros = db.Produtos.Where(p => p.Preco > 10).ToList();

// Update
var p = db.Produtos.Find(1);
if (p != null) {
    p.Preco = 2.00;
    db.SaveChanges();
}

// Delete
db.Produtos.Remove(p);
db.SaveChanges();

Bloco 8 · Async / await

Programação assíncrona

public async Task<string> DownloadAsync(string url)
{
    using var client = new HttpClient();
    string content = await client.GetStringAsync(url);
    return content;
}

// Uso
string html = await DownloadAsync("https://example.com");
Console.WriteLine(html.Length);

async + await: torna I/O não-bloqueante (essencial em web/desktop).

UC00620 · resumo

  • C# é tipado, OOP, moderno (records, patterns, nullable).
  • .NET 8 cross-platform (Windows/Linux/Mac).
  • Propriedades com get/set, auto e com lógica.
  • LINQ = poder funcional sobre colecções.
  • EF Core = ORM elegante (Code-first com migrations).
  • async/await para I/O sem bloquear.
  • Base para ASP.NET Core (web), MAUI (mobile), Unity (jogos).