Compartilhar via


Um tour pela linguagem C#

A linguagem C# é a linguagem mais popular para a plataforma .NET, um ambiente de desenvolvimento gratuito, multiplataforma e de código aberto. Os programas C# podem ser executados em muitos dispositivos diferentes, desde dispositivos de Internet das Coisas (IoT) até a nuvem e todos os outros lugares. Você pode escrever aplicativos para telefones, desktops e laptops e servidores.

O C# é uma linguagem de uso geral multiplataforma que torna os desenvolvedores produtivos ao escrever um código de alto desempenho. Com milhões de desenvolvedores, o C# é a linguagem .NET mais popular. O C# tem amplo suporte no ecossistema e em todas as cargas de trabalho do .NET. Com base em princípios orientados a objetos, ele incorpora muitos recursos de outros paradigmas, especialmente a programação funcional. Recursos de baixo nível dão suporte a cenários de alta eficiência sem escrever código não seguro. A maioria dos runtimes e bibliotecas do .NET são escritos em C# e avanços no C# geralmente beneficiam todos os desenvolvedores do .NET.

C# está na família de linguagens C. A sintaxe C# é familiar se você usou C, C++, JavaScript, TypeScript ou Java. Assim como C e C++, os ponto e vírgula (;) definem o fim das instruções. Os identificadores C# diferenciam maiúsculas de minúsculas. C# tem o mesmo uso de colchetes, { e }, instruções de controle como if, else e switch, e construções de loop como for, e while. C# também possui uma instrução foreach para qualquer tipo de coleção.

Olá, mundo

O programa "Hello, World" é usado tradicionalmente para introduzir uma linguagem de programação. Este é para C#:

// This line prints "Hello, World" 
Console.WriteLine("Hello, World");

A linha que começa com // é um comentário de linha única. Comentários de linha única em C# começam com // e continuam até o final da linha atual. C# também suporta comentários multilinhas. Comentários de várias linhas começam com /* e terminam com */. O método WriteLine da classe Console, que está no System namespace, produz a saída do programa. Essa classe é fornecida pelas bibliotecas de classes padrão, que, por padrão, são referenciadas automaticamente em todos os programas C#. Outro formulário de programa exige que você declare a classe e o método que contêm o ponto de entrada do programa. O compilador sintetiza esses elementos quando você usa instruções de nível superior.

Esse formato alternativo ainda é válido e contém muitos dos conceitos básicos em todos os programas C#. Muitos exemplos de C# existentes usam o seguinte formato equivalente:

using System;
namespace TourOfCsharp;

class Program
{
    static void Main()
    {
        // This line prints "Hello, World" 
        Console.WriteLine("Hello, World");
    }
}

O programa anterior "Olá, Mundo" começa com uma using diretiva que faz referência ao System namespace. Namespaces fornecem um meio hierárquico de organizar bibliotecas e programas em C#. Namespaces contêm tipos e outros namespaces—por exemplo, o namespace System contém muitos tipos, como a classe Console referenciada no programa, e muitos outros namespaces, como IO e Collections. A diretiva using que faz referência a um determinado namespace permite o uso não qualificado dos tipos que são membros desse namespace. Devido à diretiva using, o programa pode usar Console.WriteLine como um atalho para System.Console.WriteLine. No exemplo anterior, esse namespace foi implicitamente incluído.

A classe Program declarada pelo programa "Hello, World" tem um único membro, o método chamado Main. O método Main é declarado com o modificador static. Embora os métodos de instância possam fazer referência a uma determinada instância de objeto delimitador usando a palavra-chave this, métodos estáticos operam sem referência a um objeto específico. Por convenção, quando não há instruções de nível superior, um método estático chamado Main serve como ponto de entrada de um programa C#. A classe que contém o Main método normalmente é nomeada Program.

Dica

Os exemplos neste artigo fornecem uma primeira visão do código C#. Alguns exemplos podem mostrar elementos de C# com os quais você não está familiarizado. Quando estiver pronto para aprender C#, comece com nossos tutoriais para iniciantes ou mergulhe nos links de cada seção. Se você tiver experiência em Java, JavaScript, TypeScript ou Python, leia nossas dicas para ajudá-lo a encontrar as informações necessárias para aprender rapidamente o C#.

Aplicativos baseados em arquivo

C# é uma linguagem compilada . Na maioria dos programas C#, você usa o dotnet build comando para compilar um grupo de arquivos de origem em um pacote binário. Em seguida, use o dotnet run comando para executar o programa. (Você pode simplificar esse processo porque dotnet run compila o programa antes de executá-lo, se necessário.) Essas ferramentas dão suporte a uma linguagem avançada de opções de configuração e comutadores de linha de comando. A dotnet CLI (interface de linha de comando), que está incluída no SDK do .NET, fornece muitas ferramentas para gerar e modificar arquivos C#.

A partir do C# 14 e do .NET 10, você pode criar aplicativos baseados em arquivo, o que simplifica a criação e a execução de programas C#. Use o dotnet run comando para executar um programa contido em um único *.cs arquivo. Por exemplo, se o código a seguir for armazenado em um arquivo nomeado hello-world.cs, você poderá executá-lo digitando dotnet run hello-world.cs:

#!/usr/local/share/dotnet/dotnet run
Console.WriteLine("Hello, World!");

A primeira linha do programa contém a sequência #! (shebang) para shells Unix. O local da dotnet CLI pode variar em distribuições diferentes. Em qualquer sistema unix, se você definir a permissão execute (+x) em um arquivo C# que contenha a diretiva shebang, poderá executar o arquivo C# diretamente da linha de comando:

./hello-world.cs

A origem desses programas deve ser um único arquivo, mas caso contrário, toda a sintaxe C# é válida. Você pode usar aplicativos baseados em arquivo para pequenos utilitários de linha de comando, protótipos ou outros experimentos.

Recursos familiares do C#

C# é acessível para iniciantes, mas oferece recursos avançados para desenvolvedores experientes que escrevem aplicativos especializados. Você pode ser produtivo rapidamente. Você pode aprender técnicas mais especializadas conforme necessário para suas aplicações.

Os aplicativos C# se beneficiam do gerenciamento automático de memória do .NET Runtime. Os aplicativos C# também usam as extensas bibliotecas de tempo de execução fornecidas pelo .NET SDK. Alguns componentes são independentes de plataforma, como bibliotecas de sistemas de arquivos, coleções de dados e bibliotecas matemáticas. Outras são específicas para uma única carga de trabalho, como as bibliotecas Web ASP.NET Core ou a biblioteca .NET MAUI UI. Um rico ecossistema de código aberto no NuGet aumenta as bibliotecas que fazem parte do tempo de execução. Essas bibliotecas fornecem ainda mais componentes que você pode usar.

C# é uma linguagem fortemente tipada. Cada variável que você declara possui um tipo conhecido em tempo de compilação. O compilador ou ferramentas de edição informam se você está usando esse tipo incorretamente. Você pode corrigir esses erros antes mesmo de executar o programa. Tipos de dados fundamentais são integrados à linguagem e ao tempo de execução: tipos de valor como int, double, char, tipos de referência como string, matrizes e outras coleções. Ao escrever seus programas, você cria seus próprios tipos. Esses tipos podem ser struct tipos para valores ou class tipos que definem o comportamento orientado a objetos. Você pode adicionar o modificador record aos tipos struct ou class para que o compilador sintetize o código para comparações de igualdade. Você também pode criar definições interface, que definem um contrato, ou um conjunto de membros, que um tipo que implementa essa interface deve fornecer. Você também pode definir tipos e métodos genéricos. Genéricos usam parâmetros de tipo para fornecer um espaço reservado para um tipo real quando usados.

Ao escrever o código, você define funções, também chamadas de métodos, como membros dos tipos struct e class. Esses métodos definem o comportamento dos seus tipos. Os métodos podem estar sobrecarregados, com diferentes números ou tipos de parâmetros. Os métodos podem opcionalmente retornar um valor. Além dos métodos, os tipos C# podem ter propriedades, que são elementos de dados apoiados por funções chamadas acessadores. Os tipos C# podem definir events, que permitem que um tipo notifique os assinantes sobre ações importantes. C# oferece suporte a técnicas orientadas a objetos, como herança e polimorfismo para tipos class.

Os aplicativos C# usam exceções para relatar e tratar erros. Essa prática é familiar se você usou C++ ou Java. Seu código lança uma exceção quando não consegue fazer o que foi planejado. Outro código, não importa quantos níveis subam na pilha de chamadas, pode opcionalmente ser recuperado usando um bloco try - catch.

Recursos distintos do C#

Alguns elementos do C# podem ser menos familiares.

C# fornece correspondência de padrões. Essas expressões permitem inspecionar dados e tomar decisões com base em suas características. A correspondência de padrões fornece uma ótima sintaxe para fluxo de controle baseado em dados. O código a seguir mostra como os métodos para as operações booleanas e, or e xor podem ser expressos usando a sintaxe de correspondência de padrões:

public static bool Or(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => true,
        (true, false) => true,
        (false, true) => true,
        (false, false) => false,
    };

public static bool And(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => true,
        (true, false) => false,
        (false, true) => false,
        (false, false) => false,
    };
public static bool Xor(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => false,
        (true, false) => true,
        (false, true) => true,
        (false, false) => false,
    };

As expressões de correspondência de padrões podem ser simplificadas usando _ como um resumo para qualquer valor. O exemplo a seguir mostra como você pode simplificar os métodos e:

public static bool ReducedAnd(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => true,
        (_, _) => false,
    };

Os exemplos anteriores também declaram tuplas, que são estruturas de dados leves. Uma tupla é uma sequência ordenada e de comprimento fixo de valores com nomes opcionais e tipos específicos. Você delimita a sequência com os caracteres ( e ). A declaração (left, right) define uma tupla com dois valores boolianos: left e right. Cada braço de comutador declara um valor de tupla, como (true, true). As tuplas fornecem sintaxe conveniente para declarar um único valor com vários valores.

As expressões de coleção fornecem uma sintaxe comum para fornecer valores de coleção. Você escreve valores ou expressões entre os caracteres [ e ], e o compilador converte essa expressão no tipo de coleção necessário.

int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
List<string> names = ["Alice", "Bob", "Charlie", "David"];

IEnumerable<int> moreNumbers = [.. numbers, 11, 12, 13];
IEnumerable<string> empty = [];

O exemplo anterior mostra diferentes tipos de coleção que podem ser inicializados usando expressões de coleção. Um exemplo usa a [] expressão de coleção vazia para declarar uma coleção vazia. Outro exemplo usa o ..elemento spread para expandir uma coleção e adicionar todos os seus valores à expressão de coleção.

Você pode usar expressões de índice e intervalo para recuperar um ou mais elementos de uma coleção indexável:

string second = names[1]; // 0-based index
string last = names[^1]; // ^1 is the last element
int[] smallNumbers = numbers[0..5]; // 0 to 4

O ^ índice indica desde o final e não desde o início. O elemento ^0 está logo após o final da coleção, então ^1 é o último elemento. A .. em uma expressão de intervalo indica o intervalo de elementos a serem incluídos. O intervalo começa com o primeiro índice e inclui todos os elementos até, mas não incluindo, o elemento no último índice.

Para obter mais informações sobre expressões de índice e intervalo, consulte o artigo Explorar índices e intervalos .

Consulta integrada de linguagem (LINQ) fornece uma sintaxe comum baseada em padrões para consultar ou transformar qualquer coleção de dados. LINQ unifica a sintaxe para consultar coleções na memória, dados estruturados como XML ou JSON, armazenamento de banco de dados e até mesmo APIs de dados baseadas em nuvem. Você aprende um conjunto de sintaxe e pode pesquisar e manipular dados independentemente de seu armazenamento. A consulta a seguir encontra todos os alunos cuja média de notas é superior a 3,5:

var honorRoll = from student in Students
                where student.GPA > 3.5
                select student;

A consulta anterior funciona para muitos tipos de armazenamento representados por Students. Pode ser uma coleção de objetos, uma tabela de banco de dados, um blob de armazenamento em nuvem ou uma estrutura XML. A mesma sintaxe de consulta funciona para todos os tipos de armazenamento.

O modelo de programação assíncrona baseado em tarefas permite que você escreva código que parece ser executado de forma síncrona, mesmo que seja executado de forma assíncrona. Ele utiliza as palavras-chave async e await para descrever métodos assíncronos e quando uma expressão é avaliada de forma assíncrona. O exemplo a seguir aguarda uma solicitação da Web assíncrona. Quando a operação assíncrona for concluída, o método retornará o comprimento da resposta:

public static async Task<int> GetPageLengthAsync(string endpoint)
{
    var client = new HttpClient();
    var uri = new Uri(endpoint);
    byte[] content = await client.GetByteArrayAsync(uri);
    return content.Length;
}

C# também oferece suporte a uma instrução await foreach para iterar uma coleção apoiada por uma operação assíncrona, como uma API de paginação GraphQL. O exemplo a seguir lê dados em partes, retornando um iterador que fornece acesso a cada elemento quando estiver disponível:

public static async IAsyncEnumerable<int> ReadSequence()
{
    int index = 0;
    while (index < 100)
    {
        int[] nextChunk = await GetNextChunk(index);
        if (nextChunk.Length == 0)
        {
            yield break;
        }
        foreach (var item in nextChunk)
        {
            yield return item;
        }
        index++;
    }
}

Os chamadores podem iterar a coleção usando uma instrução await foreach:

await foreach (var number in ReadSequence())
{
    Console.WriteLine(number);
}

Finalmente, como parte do ecossistema .NET, você pode usar o Visual Studio ou o Visual Studio Code com o C# DevKit. Essas ferramentas fornecem uma compreensão avançada de C#, incluindo o código que você escreve. Eles também fornecem recursos de depuração.