Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O C# 12 inclui os novos recursos a seguir. Você pode experimentar esses recursos usando a versão mais recente do Visual Studio 2022 ou o SDK do .NET 8.
Construtores primários – introduzidos no Visual Studio versão 17.6 versão 2 de 2022.
Expressões de coleção – Introduzidas no Visual Studio versão 17.7 versão 5 de 2022.
Matrizes embutidas – introduzidas no Visual Studio versão 17.7 versão 3 de 2022.
Parâmetros opcionais em expressões lambda – introduzidos no Visual Studio versão 17.5 versão 2 de 2022.
ref readonlyparâmetros – introduzidos no Visual Studio versão 17.8 versão 2 de 2022.Alias qualquer tipo – introduzido no Visual Studio versão 17.6 versão 3 de 2022.
Atributo experimental – Introduzido no Visual Studio versão 17.7 versão 3 de 2022.
Interceptadores - Recurso de visualização Introduzido no Visual Studio versão 17.7 versão 3 de 2022.
O C# 12 tem suporte no .NET 8. Para obter mais informações, confira Controle de versão da linguagem C#.
Você pode baixar o SDK mais recente do .NET 8 na página de downloads do .NET. Você também pode baixar Visual Studio 2022, que inclui o SDK do .NET 8.
Note
Estamos interessados em seus comentários sobre esses recursos. Se você encontrar problemas com qualquer um desses novos recursos, crie um problema no repositório dotnet/roslyn.
Construtores primários
Agora você pode criar construtores primários em qualquer class e struct. Construtores primários não são mais restritos a record tipos. Os parâmetros do construtor primário estão no escopo de todo o corpo da classe. Para garantir que todos os parâmetros do construtor primário sejam definitivamente atribuídos, todos os construtores declarados explicitamente devem chamar o construtor primário usando this() sintaxe. Adicionar um construtor primário a um class impede que o compilador declare um construtor implícito sem parâmetros. Em um structconstrutor implícito sem parâmetros inicializa todos os campos, incluindo parâmetros de construtor primário para o padrão de 0 bit.
O compilador gera propriedades públicas para parâmetros de construtor primário apenas em record tipos, tipos record class ou record struct tipos. Classes e structs não gravados podem nem sempre querer esse comportamento para parâmetros de construtor primário.
Você pode saber mais sobre construtores primários no tutorial para explorar construtores primários e no artigo sobre construtores de instância.
Expressões de coleção
As expressões de coleção introduzem uma nova sintaxe terse para criar valores comuns de coleção. A inlining other collections into these values is possible using a spread element ..e.
Vários tipos semelhantes à coleção podem ser criados sem a necessidade de suporte a BCL externo. Esses tipos são:
- Tipos de matriz, como
int[]. - System.Span<T> e System.ReadOnlySpan<T>.
- Tipos que dão suporte a inicializadores de coleção, como System.Collections.Generic.List<T>.
Os exemplos a seguir mostram usos de expressões de coleção:
// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];
// Create a list:
List<string> b = ["one", "two", "three"];
// Create a span
Span<char> c = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];
// Create a jagged 2D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
// Create a jagged 2D array from variables:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[][] twoDFromVariables = [row0, row1, row2];
O elemento spread, ..e em uma expressão de coleção, adiciona todos os elementos nessa expressão. O argumento deve ser um tipo de coleção. Os exemplos a seguir mostram como o elemento spread funciona:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[] single = [.. row0, .. row1, .. row2];
foreach (var element in single)
{
Console.Write($"{element}, ");
}
// output:
// 1, 2, 3, 4, 5, 6, 7, 8, 9,
O elemento spread avalia cada elemento da expressão de enumerações. Cada elemento é incluído na coleção de saída.
Você pode usar expressões de coleção em qualquer lugar que precisar de uma coleção de elementos. Eles podem especificar o valor inicial de uma coleção ou ser passados como argumentos para métodos que assumem tipos de coleção. Você pode saber mais sobre expressões de coleção no artigo de referência de linguagem sobre expressões de coleção ou a especificação do recurso.
Parâmetros ref readonly
O C# adicionou in parâmetros como uma maneira de passar referências somente leitura.
in os parâmetros permitem variáveis e valores e podem ser usados sem nenhuma anotação nos argumentos.
A adição de ref readonly parâmetros permite mais clareza para APIs que podem estar usando ref parâmetros ou in parâmetros:
- As APIs criadas antes
inda introdução podem ser usadasrefmesmo que o argumento não seja modificado. Essas APIs podem ser atualizadas comref readonly. Não será uma alteração significativa para os chamadores, como seria se orefparâmetro fosse alterado parain. Um exemplo é System.Runtime.InteropServices.Marshal.QueryInterface. - APIs que tomam um
inparâmetro, mas logicamente exigem uma variável. Uma expressão de valor não funciona. Um exemplo é System.ReadOnlySpan<T>.ReadOnlySpan<T>(T). - APIs que usam
refporque exigem uma variável, mas não modificam essa variável. Um exemplo é System.Runtime.CompilerServices.Unsafe.IsNullRef.
Para saber mais sobre ref readonly parâmetros, consulte o artigo sobre modificadores de parâmetro na referência de linguagem ou a especificação de recurso ref readonly parameters .
Parâmetros lambda padrão
Agora você pode definir valores padrão para parâmetros em expressões lambda. A sintaxe e as regras são iguais à adição de valores padrão para argumentos a qualquer método ou função local.
Você pode saber mais sobre parâmetros padrão em expressões lambda no artigo sobre expressões lambda.
Alias de qualquer tipo
Você pode usar a diretiva de alias using para alias qualquer tipo, não apenas tipos nomeados. Isso significa que você pode criar aliases semânticos para tipos de tupla, tipos de matriz, tipos de ponteiro ou outros tipos não seguros. Para obter mais informações, consulte a especificação do recurso. Para obter um exemplo de passo a passo de refatoração, consulte Refatorar seu código usando alias qualquer tipo no blog .NET.
Matrizes embutidas
Matrizes embutidas são usadas pela equipe de runtime e outros autores de biblioteca para melhorar o desempenho em seus aplicativos. As matrizes embutidas permitem que um desenvolvedor crie uma matriz de tamanho fixo em um struct tipo. Um struct com um buffer embutido deve fornecer características de desempenho semelhantes a um buffer de tamanho fixo não seguro. Você provavelmente não declarará suas próprias matrizes embutidas, mas as usará de forma transparente quando elas forem expostas como System.Span<T> ou System.ReadOnlySpan<T> objetos de APIs de runtime.
Uma matriz embutida é declarada semelhante à seguinte struct:
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
Você os usa como qualquer outra matriz:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
buffer[i] = i;
}
foreach (var i in buffer)
{
Console.WriteLine(i);
}
A diferença é que o compilador pode aproveitar informações conhecidas sobre uma matriz embutida. Você provavelmente consumirá matrizes embutidas como faria com qualquer outra matriz. Para obter mais informações sobre como declarar matrizes embutidas, consulte a referência de idioma sobre struct tipos.
Atributo experimental
Tipos, métodos ou assemblies podem ser marcados com a indicação System.Diagnostics.CodeAnalysis.ExperimentalAttribute de um recurso experimental. O compilador emitirá um aviso se você acessar um método ou tipo anotado com o ExperimentalAttribute. Todos os tipos incluídos em um assembly marcado com o Experimental atributo são experimentais. Você pode ler mais no artigo sobre atributos gerais lidos pelo compilador ou a especificação do recurso.
Interceptadores
Warning
Interceptores são um recurso experimental, disponível no modo de visualização com C# 12. O recurso pode estar sujeito a alterações ou remoção interruptivas em uma versão futura. Portanto, não é recomendável para aplicativos lançados ou de produção.
Para usar interceptadores, o projeto do usuário deve especificar a propriedade <InterceptorsPreviewNamespaces>. Esta é uma lista de namespaces que têm permissão para conter interceptadores.
Por exemplo: <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>
Um interceptor é um método que pode substituir declarativamente uma chamada a um método interceptável por uma chamada para si mesmo em tempo de compilação. Essa substituição ocorre fazendo com que o interceptador declare os locais de origem das chamadas que intercepta. Os interceptores fornecem uma instalação limitada para alterar a semântica do código existente adicionando um novo código a uma compilação, por exemplo, em um gerador de origem.
Você usa um interceptor como parte de um gerador de origem para modificar, em vez de adicionar código a uma compilação de origem existente. O gerador de origem substitui chamadas a um método interceptável por uma chamada para o método interceptor .
Se você estiver interessado em experimentar interceptores, saiba mais lendo a especificação do recurso. Se você usar o recurso, mantenha-se atualizado com quaisquer alterações na especificação de recurso para esse recurso experimental. Se o recurso for finalizado, adicionaremos mais diretrizes neste site.