Fundamentos práticos de C# e .NET

Setup, execução com evidência e debug como método

Por Fábio Linhares • Infnet

Qual a ideia aqui?

Estas questões não são “sobre decorar C#”. Elas são sobre ganhar o direito de dizer: “eu consigo abrir um ambiente limpo, criar um projeto, fazer o programa rodar, entender quando ele falha e corrigir com método”. É o tipo de base que separa quem fica preso em tutorial de quem consegue caminhar sozinho.

O desafio aqui é duplo. Primeiro, dominar o terreno: .NET como plataforma, C# como linguagem, IDE como ferramenta, e o ciclo completo de desenvolvimento (criar → compilar → executar → depurar). Segundo, desenvolver o reflexo correto quando algo dá errado: distinguir erro de compilação (não roda) de erro de lógica (roda, mas faz errado), ler mensagens do compilador sem pânico e usar o debugger como instrumento — não como superstição.

Quem resolve este TP com consistência costuma terminar com estas competências:

  • Autonomia de setup: preparar um ambiente local com .NET/IDE, criar projetos e reproduzir o processo sem depender de “máquina mágica”.
  • Alfabetização de plataforma: entender C# ↔ .NET, o papel do runtime (CLR) e por que as bibliotecas do .NET são parte do poder real do ecossistema.
  • Execução com evidência: compilar e rodar sabendo o que está acontecendo (Debug/Release, build, output) e validando pelo que aparece na tela.
  • Debug como método: pausar, observar, formular hipótese, testar, corrigir e validar — em vez de “mexer até parar de dar erro”.
  • Fundamentos aplicados: tipos básicos, I/O em console, interpolação/formatos simples e robustez mínima (entrada vazia).
  • Leitura de erro como habilidade: interpretar mensagens do compilador e corrigir a causa, não o sintoma.
  • Higiene básica: noções iniciais de organização de projeto e fluxo de trabalho (Visual Studio / VS Code / Rider).

No fim, o perfil desejado é o de iniciante sólido: alguém que inicia um projeto pequeno do zero, faz o básico funcionar, explica o que fez e corrige problemas previsíveis sem travar.

Pro tip: Trate cada erro como um experimento: hipótese → evidência (mensagem/output) → ajuste → validação.

Divisão sugerida em 4 módulos práticos:

Módulo 1 — O “motor” do .NET:

  • A jornada do código: C# compila para IL (Intermediate Language).
  • O papel do CLR: executa IL via JIT, gerencia memória (GC), exceções e carregamento.
  • Bibliotecas Base (BCL/FCL): o “poder” vem das APIs prontas (I/O, coleções, rede, LINQ etc.).

Módulo 2 — A arte da depuração:

  • Erro de compilação vs erro de lógica: primeiro impede rodar; o segundo roda errado.
  • Breakpoints e inspeção: pausar, observar variáveis, confirmar hipótese, corrigir com método.

Módulo 3 — Boas práticas e C# moderno:

  • Interpolação de strings ($"...").
  • Tratamento de nulos/entradas vazias: string.IsNullOrWhiteSpace() como mínimo de robustez.

Módulo 4 — O quebra-cabeça web (panorama):

  • ASP.NET Core: motor HTTP no servidor (pipeline, rotas, auth).
  • EF Core: ORM (classes ↔ tabelas; LINQ ↔ SQL; migrações).
  • Razor Pages: UI server-side (HTML + C#) com organização por página.
Pro tip: Evite estudar “tudo ao mesmo tempo”: primeiro rode um console app do zero; depois acrescente camadas.

.NET é uma plataforma/ecossistema para construir e executar aplicações. Ela inclui runtime, bibliotecas padrão e ferramentas (SDK). Na prática, “programar em C#” costuma significar “escrever código que roda sobre o runtime do .NET e consome as bibliotecas do .NET”.

Como C# se integra ao .NET: C# compila para IL (Intermediate Language). Esse IL roda sobre o .NET (via CLR), e o programa usa a Base Class Library para operações comuns (I/O, coleções, rede, etc.). Em geral, C# não vira código nativo direto; vira IL + metadata, e o runtime faz o resto.

Papel do CLR (Common Language Runtime): é o “motor” de execução. Gerencia memória (GC), faz JIT (IL → nativo), trata exceções, tipagem em runtime, carregamento de assemblies e outros serviços do ambiente.

Papel da FCL/BCL: conjunto de bibliotecas prontas do .NET (string, List<T>, Dictionary<,>, Stream, File, HttpClient, LINQ...). Sem biblioteca, linguagem vira “só sintaxe”; com biblioteca, vira capacidade real.

Verificação rápida: dotnet --info mostra SDK/runtime; criar um console app e rodar confirma o pipeline funcionando.

Pro tip: Quando estiver confuso, pense assim: C# escreve; o compilador traduz para IL; o CLR executa; a BCL resolve a vida.

ASP.NET Core: framework web do .NET para criar APIs, sites e serviços HTTP. Fornece pipeline de middleware, roteamento, controllers/minimal APIs, autenticação/autorização etc. Em resumo: “o motor do servidor web”.

Entity Framework Core (EF Core): ORM (Object-Relational Mapper). Faz a ponte entre classes C# e tabelas do banco. Mapeia entidades, traduz LINQ em SQL, suporta migrações, tracking de mudanças e persistência. Não é obrigatório, mas é comum em projetos com banco relacional.

Razor Pages: modelo de UI server-side baseado em páginas, com Razor (HTML + C#). Alternativa ao MVC “clássico” para apps com páginas e formulários, com organização mais direta.

Verificação rápida: criar um “ASP.NET Core Web App (Razor Pages)” e um “ASP.NET Core Web API”; no segundo, adicionar EF Core + provider (SQLite/SQL Server) e fazer um CRUD mínimo.

Pro tip: Guarde a tríade: ASP.NET Core (HTTP) + EF Core (dados) + Razor Pages (telas server-side).

Visual Studio (IDE completa):

  • Pontos fortes: experiência “tudo no lugar” para .NET (debugger, profiler, tooling, publish, testes, integração com MSBuild).
  • Pontos fracos: mais pesado e mais “opinativo”.

VS Code (editor + extensões):

  • Pontos fortes: leve, rápido, multi-linguagem; ótimo para stacks mistas.
  • Pontos fracos: C# depende de extensões/config; experiência varia.

Rider (JetBrains):

  • Pontos fortes: refatoração e navegação excelentes; muito forte em projetos grandes; cross-platform sólido.
  • Pontos fracos: geralmente pago; pode ser pesado em máquinas fracas.

Para iniciantes: Visual Studio costuma reduzir atrito por ter menos “peças soltas”. VS Code é ótimo, mas exige maturidade de setup. Rider é excelente se a licença não for obstáculo.

Pro tip: Ferramenta boa é a que reduz fricção hoje e não te prende amanhã. Para começar, minimize setup.

Passos mínimos (sem prints):

  1. Instalar Visual Studio Community 2022.
  2. No instalador, marcar o workload “Desktop development with C#”.
  3. Abrir o Visual Studio → Create a new project → Console App (C#) → criar.
  4. Rodar o projeto (F5 ou Ctrl+F5) e confirmar execução no console.

Evidência: projeto cria sem erro, compila e roda. Em paralelo, no terminal: dotnet --version retorna a versão do SDK.

Pro tip: Se o Visual Studio “parecer mágico”, confirme no terminal: dotnet --info e dotnet --version.

Forma moderna (top-level statements, comum em .NET 6+): uma única linha já é suficiente.

Forma clássica: útil para entender ponto de entrada (Main) e estrutura de programa.

Importante: use apenas uma das formas por arquivo Program.cs (não misture os dois exemplos no mesmo arquivo).

Verificação: ao executar, a saída deve conter exatamente “Hello World”.

// Forma moderna (top-level statements):
Console.WriteLine("Hello World");
// Forma clássica (Program/Main):
using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Hello World");
    }
}
Pro tip: Se “Hello World” falhar, o problema quase sempre é ambiente/projeto — ótimo para diagnosticar cedo.

“Build Solution” executa o processo de compilação (MSBuild) e gera o assembly em bin/Debug (ou bin/Release).

Se houver erro, aparece na Error List e no Output.

Verificação alternativa (mesmo conceito via CLI): na pasta do projeto, rodar dotnet build. Se compilar sem erro, o código está consistente e o projeto está bem configurado.

dotnet build
Pro tip: Aprenda a alternar entre IDE e CLI: quando um falha, o outro ajuda a isolar o problema.

Detalhe que separa “sintaxe” de “debug”:

  • Console.Writeline(...) (com L minúsculo) é erro de compilação. Se não compila, não existe “rodar com breakpoint”; primeiro corrige para compilar.
  • Debugger (breakpoint) é mais útil para erro de lógica (compila, roda, mas faz algo errado).

Dois jeitos corretos de ensinar:

A) Caso de erro de compilação (corrigir antes)
Código com erro: Console.Writeline(...)
Correção: Console.WriteLine(...)

B) Caso de depuração de lógica (compila e usa breakpoint)
Código compila, mas texto está errado (“word” em vez de “world”).
Procedimento: breakpoint → rodar (F5) → inspecionar → corrigir → rodar novamente e validar.

// Erro de compilação (não compila):
Console.Writeline("Hello, word!");

// Correção:
Console.WriteLine("Hello, world!");

// Erro de lógica (compila, mas está “errado”):
Console.WriteLine("Hello, word!");
Pro tip: Regra de ouro: se não compila, não é “debug”; é leitura de erro e correção de causa.

Console.ReadLine() pode retornar null. Mesmo quando não retorna, o usuário pode apertar Enter vazio.

Use string.IsNullOrWhiteSpace() para tratar os dois casos e manter o programa estável.

Verificação: digitar “Ana” deve imprimir “Olá, Ana!”. Enter vazio deve cair no caso de nome não informado.

Console.Write("Digite seu nome: ");
string? nome = Console.ReadLine();

if (string.IsNullOrWhiteSpace(nome))
{
    Console.WriteLine("Olá! (nome não informado)");
}
else
{
    Console.WriteLine($"Olá, {nome}!");
}
Pro tip: Robustez mínima é barata e evita 80% das dores iniciais: trate null e entrada vazia.

Exemplo direto com int, string e double e saída via Console.WriteLine com interpolação.

Observação útil: a exibição de double pode variar com cultura/locale. Para o TP, o essencial é compilar e imprimir os valores; cultura entra quando “formatação correta” vira requisito.

int idade = 25;
string nome = "Maria";
double altura = 1.72;

Console.WriteLine($"Nome: {nome}");
Console.WriteLine($"Idade: {idade}");
Console.WriteLine($"Altura: {altura}");
Pro tip: Interpolação ($) é o padrão moderno: mais legível e menos propenso a erro do que concatenação.

Versão objetiva: declarar string e int e imprimir uma frase completa com interpolação.

Fechamento didático: estes 10 exercícios são o aquecimento correto: ferramenta (IDE/build), ponto de entrada, saída/entrada, tipos básicos e a diferença entre erro de compilação e erro de lógica.

O salto real acontece quando a prática passa a usar (1) testes para validar comportamento e (2) debug por hipótese: “o que eu esperava ver?”, “o que vi?”, “o que isso implica?”.

string nome = "João";
int idade = 30;

Console.WriteLine($"Meu nome é {nome} e eu tenho {idade} anos");
Pro tip: Quando algo “não bate”, descreva a expectativa em uma frase. Debug bom começa em português antes de virar C#.