---
title: "Zig para Programadores C#"
url: "https://ziglang.com.br/artigos/zig-para-programadores-c/"
markdown_url: "https://ziglang.com.br/artigos/zig-para-programadores-c.MD"
description: "Guia de Zig para desenvolvedores C#. Mapeamento de conceitos: classes vs structs, LINQ vs iteradores, async/await, garbage collector vs allocators, generics vs comptime."
date: "2026-02-21"
author: "Zig Brasil"
---

# Zig para Programadores C#

Guia de Zig para desenvolvedores C#. Mapeamento de conceitos: classes vs structs, LINQ vs iteradores, async/await, garbage collector vs allocators, generics vs comptime.


## Introdução

Se você é desenvolvedor C#, Zig vai representar uma mudança significativa de paradigma. C# é uma linguagem de alto nível com garbage collector, classes, herança, LINQ e um ecossistema rico (.NET). Zig é uma linguagem de sistemas sem GC, sem classes, sem exceções e com controle manual de memória.

Isso não significa que Zig é "pior" — apenas que opera em outro nível. Este guia ajuda você a traduzir conceitos familiares de C# para Zig. Para outras perspectivas, veja [Zig para Programadores Kotlin](/artigos/zig-para-programadores-kotlin/) e [Zig para Programadores Java](/artigos/zig-para-programadores-java/).

## Mapeamento de Conceitos

| C# | Zig | Notas |
|----|-----|-------|
| `class` | `struct` | Zig não tem classes nem herança |
| `interface` | Comptime duck typing | Sem vtable |
| `var x = 42` | `const x = 42` | Inferência de tipo |
| `List<T>` | `std.ArrayList(T)` | Requer allocator |
| `Dictionary<K,V>` | `std.HashMap(K,V,...)` | Requer allocator |
| `try/catch` | `try`/`catch` (error unions) | Sem exceções |
| `using` | `defer` | Limpeza de recursos |
| `async/await` | Sem equivalente direto | Usar threads |
| `null` | `null` (optional) | Tipo `?T` |
| `Nullable<T>` | `?T` | Optionals nativos |
| Generics | `comptime` | Resolvido em compilação |
| GC | Allocators explícitos | Diferença fundamental |
| `string` | `[]const u8` | Bytes, não chars |
| LINQ | Loops explícitos | Sem query syntax |

## Classes vs Structs

C# usa classes com herança. Zig usa structs sem herança:

### C#

```csharp
public class Animal {
    public string Nome { get; set; }
    public virtual void Falar() => Console.WriteLine("...");
}

public class Cachorro : Animal {
    public override void Falar() => Console.WriteLine("Au au!");
}
```

### Zig

```zig
const Animal = struct {
    nome: []const u8,
    falarFn: *const fn (*const Animal) void,

    pub fn falar(self: *const Animal) void {
        self.falarFn(self);
    }
};

fn falarCachorro(_: *const Animal) void {
    std.debug.print("Au au!\n", .{});
}

const cachorro = Animal{
    .nome = "Rex",
    .falarFn = falarCachorro,
};
```

Em vez de herança, Zig usa composição e ponteiros de função quando polimorfismo de runtime é necessário. Para polimorfismo de compilação, use `comptime`:

```zig
fn alimentar(animal: anytype) void {
    animal.comer();
}
```

## Generics vs Comptime

### C#

```csharp
public class Pilha<T> {
    private List<T> _items = new();
    public void Push(T item) => _items.Add(item);
    public T Pop() => _items[^1]; // simplificado
}

var pilha = new Pilha<int>();
pilha.Push(42);
```

### Zig

```zig
fn Pilha(comptime T: type) type {
    return struct {
        items: std.ArrayList(T),

        const Self = @This();

        pub fn init(allocator: std.mem.Allocator) Self {
            return .{ .items = std.ArrayList(T).init(allocator) };
        }

        pub fn deinit(self: *Self) void {
            self.items.deinit();
        }

        pub fn push(self: *Self, item: T) !void {
            try self.items.append(item);
        }

        pub fn pop(self: *Self) ?T {
            return self.items.popOrNull();
        }
    };
}

var pilha = Pilha(u32).init(allocator);
defer pilha.deinit();
try pilha.push(42);
```

A diferença fundamental: generics em C# existem em runtime (com type erasure parcial para value types); em Zig, `comptime` gera código especializado para cada tipo em tempo de compilação.

## Error Handling

### C#

```csharp
try {
    var conteudo = File.ReadAllText("config.json");
    var config = JsonSerializer.Deserialize<Config>(conteudo);
}
catch (FileNotFoundException ex) {
    Console.WriteLine($"Arquivo não encontrado: {ex.FileName}");
}
catch (JsonException ex) {
    Console.WriteLine($"JSON inválido: {ex.Message}");
}
```

### Zig

```zig
const config = lerConfig("config.json") catch |err| switch (err) {
    error.FileNotFound => {
        std.debug.print("Arquivo não encontrado\n", .{});
        return;
    },
    error.InvalidJson => {
        std.debug.print("JSON inválido\n", .{});
        return;
    },
    else => return err,
};
```

Zig não tem exceções. Erros são valores de retorno tipados. O compilador garante que todo erro seja tratado ou propagado com `try`. Veja [Error Sets Customizados](/receitas/zig-error-set-customizado/) e [Error Logging](/receitas/zig-error-logging/).

## Nullable e Optional

### C#

```csharp
int? valor = null;
if (valor.HasValue) {
    Console.WriteLine(valor.Value);
}
// Ou com pattern matching
if (valor is int v) {
    Console.WriteLine(v);
}
```

### Zig

```zig
const valor: ?i32 = null;
if (valor) |v| {
    std.debug.print("{}\n", .{v});
}
// Ou com orelse
const seguro = valor orelse 0;
```

## Gerenciamento de Memória

Esta é a maior mudança para programadores C#. Em C#, o GC gerencia tudo. Em Zig, você é responsável:

### C#

```csharp
var lista = new List<string>();
lista.Add("Olá");
lista.Add("Mundo");
// GC libera quando não há mais referências
```

### Zig

```zig
var lista = std.ArrayList([]const u8).init(allocator);
defer lista.deinit(); // VOCÊ libera

try lista.append("Olá");
try lista.append("Mundo");
```

O padrão em Zig é `init` + `defer deinit` — similar ao `using` em C# mas mais explícito. Veja [ArenaAllocator](/receitas/zig-arena-allocator/) e [GeneralPurposeAllocator](/receitas/zig-general-purpose-allocator/).

## LINQ vs Loops Explícitos

C# tem LINQ para consultas declarativas. Zig usa loops explícitos:

### C#

```csharp
var resultado = numeros
    .Where(n => n > 10)
    .Select(n => n * 2)
    .OrderBy(n => n)
    .ToList();
```

### Zig

```zig
var resultado = std.ArrayList(i32).init(allocator);
defer resultado.deinit();

for (numeros) |n| {
    if (n > 10) {
        try resultado.append(n * 2);
    }
}
std.mem.sort(i32, resultado.items, {}, std.sort.asc(i32));
```

Zig é mais verboso aqui, mas o código é mais previsível em termos de alocações e performance.

## using vs defer

### C#

```csharp
using var stream = File.OpenRead("dados.bin");
using var reader = new BinaryReader(stream);
var dados = reader.ReadBytes(1024);
```

### Zig

```zig
const arquivo = try std.fs.cwd().openFile("dados.bin", .{});
defer arquivo.close();
var buffer: [1024]u8 = undefined;
const lidos = try arquivo.readAll(&buffer);
```

`defer` em Zig funciona no escopo do bloco e executa quando o bloco termina, independentemente de erro ou retorno normal. `errdefer` executa apenas em caso de erro — sem equivalente em C#. Veja [Padrões Errdefer](/receitas/zig-errdefer-pattern/).

## Testes

### C#

```csharp
[Test]
public void TestSoma() {
    Assert.AreEqual(5, Calculadora.Soma(2, 3));
}
```

### Zig

```zig
test "soma" {
    try std.testing.expectEqual(@as(i32, 5), soma(2, 3));
}
```

Testes em Zig são inline no código fonte e executados com `zig test`. Veja [Testes Unitários Básicos](/receitas/zig-teste-unitario-basico/) e [Testes com Allocator](/receitas/zig-teste-com-allocator/).

## Conclusão

A transição de C# para Zig é significativa — você troca a conveniência de uma linguagem gerenciada pelo controle total de uma linguagem de sistemas. As maiores adaptações serão o gerenciamento manual de memória, a ausência de classes/herança, e a troca de exceções por error unions.

O benefício é código sem overhead de runtime, binários pequenos, performance previsível, e a capacidade de trabalhar em qualquer nível — de drivers de hardware a aplicações de servidor.

Se você está considerando a transição de uma linguagem gerenciada para uma linguagem de sistemas, veja também nosso portal sobre <a href="https://kotlin.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'kotlin.dev.br' })">Kotlin</a>, que compartilha desafios semelhantes na migração para programação de mais baixo nível.

Para começar, visite [Introdução ao Zig](/tutoriais/introducao-ao-zig/) e [Como Instalar Zig](/tutoriais/como-instalar-zig/). Se quiser entender quando Zig é a ferramenta certa, leia [Quando Usar Zig](/artigos/quando-usar-zig/).
