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:
-
params
coleções -
Novo tipo
lock
e semântica. -
Nova sequência de fuga -
\e
. - Melhorias do tipo natural do grupo de métodos
- Acesso implícito do indexador em inicializadores de objeto
-
Habilite
ref
locais eunsafe
contextos em iteradores e métodos assíncronos -
Permitir que os tipos
ref struct
implementem interfaces. - Permitir tipos de estrutura ref como argumentos para parâmetros de tipo em genéricos.
-
Propriedades parciais e indexadores agora são permitidos nos tipos
partial
. - A prioridade de para a resolução de sobrecarga permite que os autores de bibliotecas designem uma sobrecarga como melhor do que outras.
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
.