1. O que é C# e por que ele existe
C# (lê-se "C sharp") nasceu em 2000, criado pela Microsoft sob a liderança de Anders Hejlsberg — o mesmo arquiteto por trás do Turbo Pascal, Delphi e, mais tarde, do TypeScript (sim, o mesmo TypeScript que você provavelmente já usou em cima do Node.js). Isso não é coincidência: dá pra sentir a "mão" dele tanto em C# quanto em TypeScript — os dois têm obsessão por tipos bem definidos e ferramentas de desenvolvimento de primeira classe.
A linguagem foi desenhada junto com uma plataforma chamada .NET. Isso é uma diferença estrutural importante em relação ao que você conhece do mundo JavaScript: Node.js é um runtime que você escolhe usar para rodar JS fora do browser, mas JavaScript como linguagem existe independente dele. C# e .NET, por outro lado, nasceram juntos e foram feitos um para o outro desde o primeiro dia.
Hoje o C# é padronizado pela ECMA/ISO e o .NET é open source e multiplataforma (Windows, Linux, macOS) desde a unificação no .NET 5 (2020), que encerrou a era em que existiam ".NET Framework" (só Windows) e ".NET Core" (multiplataforma) como coisas separadas.
2. Entendendo o ecossistema .NET
Para quem vem do Node.js, vale mapear as peças que você já conhece para as peças equivalentes do mundo .NET:
| Node.js / JavaScript | .NET / C# | Papel |
|---|---|---|
node (runtime) | CLR (Common Language Runtime) | Executa o código já "traduzido" |
| V8 Engine | CLR + JIT Compiler | Transforma código em instruções de máquina |
npm | NuGet | Gerenciador de pacotes |
package.json | .csproj | Manifesto do projeto e dependências |
API padrão do Node (fs, http...) | BCL (Base Class Library) | Biblioteca padrão da linguagem |
dotnet CLI | dotnet CLI | Ferramenta de linha de comando (mesmo nome!) |
A diferença mais importante, porém, é como o código chega até virar instruções que o processador entende. É isso que o diagrama abaixo mostra.
Fig. 1 — Do código-fonte ao processador: compilação (Roslyn) gera IL, e o CLR faz o JIT (Just-In-Time) na hora de rodar.
O V8 (motor do Node.js) também faz JIT — ele não interpreta puramente, ele compila JS "quente" para código de máquina em tempo real. A diferença é que em JS não existe uma etapa de compilação separada e obrigatória antes de rodar: você escreve e roda. Em C#, o compilador Roslyn precisa rodar antes e vai reclamar imediatamente se houver erro de tipo — o erro aparece no build, não em produção às 3h da manhã.
3. Instalando e criando o primeiro projeto
Assim como você usa npm init para começar um projeto Node, o .NET
tem o dotnet new:
dotnet new console -o MeuPrimeiroApp
cd MeuPrimeiroApp
dotnet run
Isso cria uma pasta com dois arquivos principais: Program.cs
(seu código) e MeuPrimeiroApp.csproj (o manifesto do projeto,
equivalente ao package.json).
// C# moderno (top-level statements, C# 9+)
Console.WriteLine("Olá, mundo!");
var nome = "Wellington";
Console.WriteLine($"Bem-vindo, {nome}!");
// Node.js, pra comparar
console.log("Olá, mundo!");
const nome = "Wellington";
console.log(`Bem-vindo, ${nome}!`);
Repare como são parecidos na superfície — string interpolation com $"..."
é o primo direto do template literal `...` do JS. A diferença de
fundo é que var nome em C# não significa "tipo dinâmico": o
compilador infere que nome é do tipo string
e isso fica travado para sempre — tentar fazer nome = 5;
depois vira erro de compilação, não um bug silencioso em produção.
4. Anatomia de um programa C#
Antes do C# 9, todo programa precisava de uma estrutura explícita com namespace, classe e
um método Main. Hoje isso ainda existe por baixo dos panos —
o "top-level statements" que você viu acima é açúcar sintático para a mesma coisa:
using System;
namespace MeuPrimeiroApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Olá, mundo!");
}
}
}
Fig. 2 — Todo namespace agrupa classes; toda classe executável tem um método Main como ponto de entrada.
| Conceito C# | Para que serve | Equivalente mental em JS |
|---|---|---|
using System; | Importa um namespace para usar sem prefixo | require / import |
namespace | Agrupa classes relacionadas, evita conflito de nomes | pastas + módulos ES |
class Program | Tudo em C# vive dentro de uma classe (ou struct) | não existe equivalente direto — JS permite funções soltas |
static void Main | Ponto de entrada que o CLR chama primeiro | topo do arquivo de entrada |
Diferente do JavaScript, em C# não existem funções soltas no nível mais alto (fora de top-level statements). Todo método vive dentro de uma classe, struct ou record. Isso vai parecer burocrático no início vindo do Node, mas é a base do porquê C# empurra tão fortemente para orientação a objetos — assunto dos capítulos 5 e 6.
5. Tipagem estática: a mudança de hábito mais importante
Se tem uma coisa que vai exigir reprogramar reflexos vindos do JS, é essa: em C#, o tipo de cada variável é decidido e verificado durante a compilação, não durante a execução. Isso muda completamente onde e quando você descobre um erro.
let idade = 30;
idade = "trinta"; // válido em JS
idade = idade + 1; // NaN — só descobre rodando
int idade = 30;
idade = "trinta"; // ERRO DE COMPILAÇÃO
// CS0029: não é possível converter
// 'string' para 'int'
Pense assim, usando sua base de Matemática: em JavaScript, o "domínio" de uma variável é implícito e pode mudar a qualquer momento durante a "função" (o programa rodando). Em C#, você declara o domínio antecipadamente e o compilador prova, antes mesmo de rodar, que nenhuma operação sai desse domínio. É mais perto de uma prova formal do que de uma execução de teste por tentativa.
6. Onde isso te leva
Com C# você troca flexibilidade imediata por garantias antecipadas. O ganho fica mais claro em projetos grandes e de longa duração — exatamente o cenário mais comum em sistemas corporativos com SQL Server por trás, que é onde este curso está mirando. Nos próximos capítulos do Módulo 1 vamos construir a linguagem peça por peça: tipos e operadores, estruturas de controle, e então orientação a objetos a fundo.