Partilhar via


O que há de novo no C# 13

O C# 13 inclui os seguintes novos recursos. Você pode experimentar esses recursos usando a versão mais recente do Visual Studio 2022 ou o SDK do .NET 9:

A partir do Visual Studio 17.12, o C# 13 inclui a palavra-chave contextual field como um recurso de visualização.

O C# 13 é suportado no .NET 9. Para obter mais informações, consulte versão de linguagem C#.

Você pode baixar o SDK mais recente do .NET 9 na página de downloads do .NET. Você também pode baixar Visual Studio 2022, que inclui o SDK do .NET 9.

Novos recursos são adicionados à página "Novidades em C#" quando estão disponíveis em versões de visualização pública. O conjunto de trabalho seção da página de status do recurso roslyn rastreia quando os próximos recursos são mesclados na ramificação principal.

Você pode encontrar todas as alterações de compatibilidade introduzidas na versão C# 13 no nosso artigo sobre alterações de compatibilidade.

Observação

Estamos interessados nos seus comentários sobre estas funcionalidades. Se você encontrar problemas com qualquer um desses novos recursos, crie um novo problema no repositório dotnet/roslyn.

params coleções

O modificador params não está limitado aos tipos de matriz. Agora você pode usar params com qualquer tipo de coleção reconhecido, incluindo System.Span<T>, System.ReadOnlySpan<T>e tipos que implementam System.Collections.Generic.IEnumerable<T> e têm um método Add. Além dos tipos de concreto, as interfaces System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.Generic.ICollection<T>e System.Collections.Generic.IList<T> também podem ser usadas.

Quando um tipo de interface é usado, o compilador sintetiza o armazenamento para os argumentos fornecidos. Você pode saber mais nas especificações das funcionalidades para as coleções params.

Por exemplo, declarações de método podem declarar intervalos como parâmetros params.

public void Concat<T>(params ReadOnlySpan<T> items)
{
    for (int i = 0; i < items.Length; i++)
    {
        Console.Write(items[i]);
        Console.Write(" ");
    }
    Console.WriteLine();
}

Novo objeto de bloqueio

O tempo de execução do .NET 9 inclui um novo tipo para sincronização de threads, o tipo System.Threading.Lock. Esse tipo fornece melhor sincronização de threads por meio de sua API. O método Lock.EnterScope() entra em um escopo exclusivo. O ref struct retornado desse processo dá suporte ao padrão Dispose() para sair do escopo exclusivo.

A instrução C# lock reconhece se o destino do bloqueio é um objeto Lock. Em caso afirmativo, ele usa a API atualizada, em vez da API tradicional que usa System.Threading.Monitor. O compilador também reconhece se você converter um objeto Lock para outro tipo e o código baseado em Monitor seria gerado. Você pode ler mais na especificação da funcionalidade para o novo objeto de bloqueio.

Esse recurso permite que você obtenha os benefícios do novo tipo de biblioteca alterando o tipo de objeto que você lock. Nenhum outro código precisa ser alterado.

Nova sequência de fuga

Você pode usar \e como uma sequência de escape literal de caracteres para o caractere ESCAPE, Unicode U+001B. Anteriormente, você usava \u001b ou \x1b. O uso de \x1b não era recomendado porque se os próximos caracteres 1b fossem dígitos hexadecimais válidos, esses caracteres se tornariam parte da sequência de escape.

Tipo natural de grupo de métodos

Este recurso faz pequenas otimizações na resolução de sobrecarga envolvendo grupos de métodos. Um grupo de métodos, como o , é um método e todas as suas sobrecargas com o mesmo nome. O comportamento anterior era para o compilador construir o conjunto completo de métodos candidatos para um grupo de métodos. Se fosse necessário um tipo natural, o tipo natural era determinado a partir do conjunto completo de métodos candidatos.

O novo comportamento é eliminar o conjunto de métodos candidatos em cada escopo, removendo os métodos candidatos que não são aplicáveis. Normalmente, os métodos removidos são métodos genéricos com a aridade errada ou restrições que não são satisfeitas. O processo continua para o próximo escopo externo somente se nenhum método candidato for encontrado. Este processo segue mais de perto o algoritmo geral para resolução de sobrecarga. Se todos os métodos candidatos encontrados em um determinado escopo não corresponderem, o grupo de métodos não terá um tipo natural.

Pode ler os detalhes das alterações na proposta , especificação.

Acesso implícito ao índice

O operador de índice implícito "do fim", ^, agora é permitido em uma expressão inicializadora de objeto. Por exemplo, agora você pode inicializar uma matriz em um inicializador de objeto, conforme mostrado no código a seguir:

public class TimerRemaining
{
    public int[] buffer { get; set; } = new int[10];
}

var countdown = new TimerRemaining()
{
    buffer =
    {
        [^1] = 0,
        [^2] = 1,
        [^3] = 2,
        [^4] = 3,
        [^5] = 4,
        [^6] = 5,
        [^7] = 6,
        [^8] = 7,
        [^9] = 8,
        [^10] = 9
    }
};

A classe TimerRemaining inclui uma matriz buffer inicializada com um comprimento de 10. O exemplo anterior atribui valores a essa matriz usando o operador de índice "from the end" (^), criando efetivamente uma matriz que conta para baixo de 9 a 0.

Em versões anteriores ao C# 13, o operador ^ não pode ser usado em um inicializador de objeto. Você precisa indexar os elementos a partir do início.

ref e unsafe em iteradores e em métodos async

Este recurso e os dois seguintes permitem que tipos ref struct utilizem novas construções. Você não os usará a menos que escreva seus próprios tipos de ref struct. O mais provável é que você veja um benefício indireto à medida que System.Span<T> e System.ReadOnlySpan<T> ganham mais funcionalidade.

Antes do C# 13, os métodos iteradores (métodos que usam yield return) e os métodos async não podiam declarar variáveis ref locais, nem ter um contexto unsafe.

Em C# 13, async métodos podem declarar variáveis locais, ref, ou variáveis locais de um tipo ref struct. No entanto, essas variáveis não podem ser acessadas através de um limite de await. Também não podem ser acessados além de uma fronteira yield return.

Esta restrição relaxada permite que o compilador permita o uso seguro e verificável de variáveis locais ref e de tipos ref struct em mais locais. Você pode usar com segurança tipos como System.ReadOnlySpan<T> nesses métodos. O compilador informa se você viola as regras de segurança.

Da mesma forma, o C# 13 permite contextos unsafe em métodos iteradores. No entanto, todas as declarações yield return e yield break devem estar em contextos seguros.

allows ref struct

Antes do C# 13, tipos ref struct não podiam ser declarados como o argumento de tipo para um tipo ou método genérico. Agora, declarações de tipo genéricas podem adicionar uma anti-restrição, allows ref struct. Essa antirestrição declara que o argumento type fornecido para esse parâmetro type pode ser um tipo ref struct. O compilador impõe regras de segurança de referência em todas as instâncias desse parâmetro de tipo.

Por exemplo, você pode declarar um tipo genérico como o código a seguir:

public class C<T> where T : allows ref struct
{
    // Use T as a ref struct:
    public void M(scoped T p)
    {
        // The parameter p must follow ref safety rules
    }
}

Isso permite que tipos como System.Span<T> e System.ReadOnlySpan<T> sejam usados com algoritmos genéricos, quando aplicável. Você pode saber mais nas atualizações para where e no artigo do guia de programação sobre restrições genéricas.

ref struct interfaces

Antes do C# 13, ref struct tipos não tinham permissão para implementar interfaces. Começando com C# 13, eles podem. Você pode declarar que um tipo de ref struct implementa uma interface. No entanto, para garantir as regras de segurança de referência, um tipo ref struct não pode ser convertido num tipo de interface. Essa conversão é uma conversão de boxe e pode violar a segurança de ref. As declarações explícitas de método de interface em uma ref struct podem ser acessadas apenas através de um parâmetro de tipo onde esse parâmetro de tipo allows ref struct. Além disso, os tipos ref struct devem implementar todos os métodos declarados numa interface, incluindo aqueles com implementação por defeito.

Saiba mais nas atualizações sobre ref struct tipos e a adição da restrição genérica allows ref struct.

Mais membros parciais

Você pode declarar propriedades partial e indexadores partial em C# 13. Propriedades parciais e indexadores geralmente seguem as mesmas regras que partial métodos: você cria um declarando declaração e um implementando declaração. As assinaturas das duas declarações devem coincidir. Uma restrição é que você não pode usar uma declaração de propriedade automática para implementar uma propriedade parcial. As propriedades que não declaram um corpo são consideradas a declaração .

public partial class C
{
    // Declaring declaration
    public partial string Name { get; set; }
}

public partial class C
{
    // implementation declaration:
    private string _name;
    public partial string Name
    {
        get => _name;
        set => _name = value;
    }
}

Pode descobrir mais no artigo relativo aos membros parciais.

Prioridade de resolução de sobrecarga

Em C# 13, o compilador reconhece o marcador OverloadResolutionPriorityAttribute para preferir uma sobrecarga em detrimento de outra. Os autores da biblioteca podem usar esse atributo para garantir que uma sobrecarga nova e melhor seja preferida a uma sobrecarga existente. Por exemplo, você pode adicionar uma nova sobrecarga com melhor desempenho. Você não quer quebrar o código existente que usa sua biblioteca, mas deseja que os usuários atualizem para a nova versão quando recompilarem. Você pode usar a prioridade de resolução de sobrecarga para informar ao compilador qual sobrecarga deve ser preferida. Sobrecargas com a prioridade mais alta são preferidas.

Este recurso destina-se aos autores de bibliotecas para evitar ambiguidade ao adicionar novas sobrecargas. Os autores de bibliotecas devem ter cuidado com este atributo para evitar confusões.

A palavra-chave field

A palavra-chave contextual field está em C# 13 como um recurso de visualização. O token field acede ao campo de apoio sintetizado do compilador num acessor de propriedade. Ele permite que você escreva um corpo de acessor sem declarar um campo de suporte explícito em sua declaração de tipo. Você pode declarar um corpo para um ou ambos os acessores de uma propriedade baseada em campo.

O recurso field é lançado como uma funcionalidade de pré-visualização. Queremos aprender com as suas experiências de utilização. Há uma possível alteração crítica ou confusão na leitura do código em tipos que também incluem um campo chamado field. Você pode usar @field ou this.field para desambiguar entre a palavra-chave field e o identificador.

Importante

A palavra-chave field é um recurso de visualização no C# 13. Você deve estar usando o .NET 9 e definir seu elemento <LangVersion> para preview em seu arquivo de projeto para usar a palavra-chave contextual field.

Você deve ter cuidado ao usar o recurso de palavra-chave field em uma classe que tem um campo chamado field. A nova palavra-chave field oculta um campo chamado field no escopo de um acessor de propriedade. Você pode alterar o nome da variável field ou usar o token @ para fazer referência ao identificador field como @field. Você pode saber mais lendo a especificação do recurso para a palavra-chave field.

Se experimentares esta funcionalidade e tiveres comentários, adiciona-os ao problema associado ao recurso no repositório csharplang.

Ver também