O que há de novo no C# 11

Os seguintes recursos foram adicionados ao C# 11:

C# 11 é suportado no .NET 7. Para obter mais informações, consulte Versionamento de linguagem C#.

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

Nota

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 .

Atributos genéricos

Você pode declarar uma classe genérica cuja classe base é System.Attribute. Esse recurso fornece uma sintaxe mais conveniente para atributos que exigem um System.Type parâmetro. Anteriormente, você precisaria criar um atributo que tomasse um Type como parâmetro de construtor:

// Before C# 11:
public class TypeAttribute : Attribute
{
   public TypeAttribute(Type t) => ParamType = t;

   public Type ParamType { get; }
}

E para aplicar o atributo, use o typeof operador:

[TypeAttribute(typeof(string))]
public string Method() => default;

Usando esse novo recurso, você pode criar um atributo genérico:

// C# 11 feature:
public class GenericAttribute<T> : Attribute { }

Em seguida, especifique o parâmetro type para usar o atributo:

[GenericAttribute<string>()]
public string Method() => default;

Você deve fornecer todos os parâmetros de tipo ao aplicar o atributo. Em outras palavras, o tipo genérico deve ser totalmente construído. No exemplo acima, os parênteses vazios (( e )) podem ser omitidos, pois o atributo não tem argumentos.

public class GenericType<T>
{
   [GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.
   public string Method() => default;
}

Os argumentos de tipo devem satisfazer as mesmas restrições que o typeof operador. Tipos que exigem anotações de metadados não são permitidos. Por exemplo, os seguintes tipos não são permitidos como o parâmetro type:

  • dynamic
  • string? (ou qualquer tipo de referência anulável)
  • (int X, int Y) (ou qualquer outro tipo de tupla usando sintaxe de tupla C#).

Esses tipos não são representados diretamente nos metadados. Eles incluem anotações que descrevem o tipo. Em todos os casos, você pode usar o tipo subjacente:

  • object para dynamic.
  • string em vez de string?.
  • ValueTuple<int, int> em vez de (int X, int Y).

Suporte matemático genérico

Existem vários recursos de linguagem que permitem o suporte matemático genérico:

  • static virtual Membros em interfaces
  • operadores definidos pelo usuário verificados
  • Operadores de turno relaxados
  • operador de turno à direita não assinado

Você pode adicionar static abstract ou static virtual membros em interfaces para definir interfaces que incluem operadores sobrecarregados, outros membros estáticos e propriedades estáticas. O cenário principal para esse recurso é usar operadores matemáticos em tipos genéricos. Por exemplo, você pode implementar a System.IAdditionOperators<TSelf, TOther, TResult> interface em um tipo que implementa operator +o . Outras interfaces definem outras operações matemáticas ou valores bem definidos. Você pode aprender sobre a nova sintaxe no artigo sobre interfaces. As interfaces que incluem static virtual métodos são normalmente interfaces genéricas. Além disso, a maioria declarará uma restrição de que o parâmetro type implementa a interface declarada.

Você pode aprender mais e experimentar o recurso no tutorial Explore static abstract interface members, ou no Preview features in .NET 6 – generic math blog post.

A matemática genérica criou outros requisitos sobre a linguagem.

  • operador de deslocamento à direita não assinado: Antes do C# 11, para forçar um deslocamento para a direita não assinado, você precisaria converter qualquer tipo de inteiro assinado para um tipo não assinado, executar o turno e, em seguida, converter o resultado de volta para um tipo assinado. A partir do C# 11, você pode usar o , o operador de turno >>>não assinado.
  • Requisitos do operador de turno relaxado: o C# 11 remove o requisito de que o segundo operando deve ser um int ou implicitamente conversível em int. Essa alteração permite que tipos que implementam interfaces matemáticas genéricas sejam usados nesses locais.
  • operadores definidos pelo usuário verificados e não verificados: os desenvolvedores agora podem definir checked operadores unchecked aritméticos. O compilador gera chamadas para a variante correta com base no contexto atual. Você pode ler mais sobre checked operadores no artigo sobre operadores aritméticos.

Numérico IntPtr e UIntPtr

Os nint e nuint tipos agora alias System.IntPtr e System.UIntPtr, respectivamente.

Novas linhas em interpolações de cadeia

O texto dentro dos { e } caracteres para uma interpolação de cadeia de caracteres agora pode abranger várias linhas. O texto entre os marcadores e } é analisado { como C#. Qualquer C# legal, incluindo novas linhas, é permitido. Esse recurso facilita a leitura de interpolações de cadeia de caracteres que usam expressões C# mais longas, como expressões de correspondência switch de padrões ou consultas LINQ.

Você pode saber mais sobre o recurso de novas linhas no artigo interpolações de cadeia de caracteres na referência de idioma.

Padrões de lista

Os padrões de lista estendem a correspondência de padrões para corresponder a sequências de elementos em uma lista ou matriz. Por exemplo, sequence is [1, 2, 3] é true quando o sequence é uma matriz ou uma lista de três inteiros (1, 2 e 3). Você pode combinar elementos usando qualquer padrão, incluindo constante, tipo, propriedade e padrões relacionais. O padrão de descarte (_) corresponde a qualquer elemento único, e o novo padrão de intervalo (..) corresponde a qualquer sequência de zero ou mais elementos.

Você pode saber mais detalhes sobre padrões de lista no artigo de correspondência de padrões na referência de idioma.

Conversão de grupo de método melhorada para delegado

O padrão C# em conversões de grupo de método agora inclui o seguinte item:

  • A conversão é permitida (mas não necessária) para usar uma instância delegada existente que já contenha essas referências.

As versões anteriores do padrão proibiam o compilador de reutilizar o objeto delegado criado para uma conversão de grupo de métodos. O compilador C# 11 armazena em cache o objeto delegado criado a partir de uma conversão de grupo de métodos e reutiliza esse único objeto delegado. Esse recurso foi disponibilizado pela primeira vez no Visual Studio 2022 versão 17.2 como um recurso de visualização e no .NET 7 Preview 2.

Literais de cadeia de caracteres brutos

Literais de cadeia de caracteres brutos são um novo formato para literais de cadeia de caracteres. Os literais de cadeia de caracteres brutos podem conter texto arbitrário, incluindo espaço em branco, novas linhas, aspas incorporadas e outros caracteres especiais sem exigir sequências de escape. Um literal de cadeia de caracteres bruto começa com pelo menos três caracteres de aspas duplas ("""). Termina com o mesmo número de caracteres de aspas duplas. Normalmente, um literal de cadeia de caracteres bruto usa três aspas duplas em uma única linha para iniciar a cadeia de caracteres e três aspas duplas em uma linha separada para finalizar a cadeia de caracteres. As novas linhas que seguem a cotação de abertura e precedem a cotação de encerramento não estão incluídas no conteúdo final:

string longMessage = """
    This is a long message.
    It has several lines.
        Some are indented
                more than others.
    Some should start at the first column.
    Some have "quoted text" in them.
    """;

Qualquer espaço em branco à esquerda das aspas duplas de fechamento será removido do literal da cadeia de caracteres. Literais de cadeia de caracteres brutos podem ser combinados com interpolação de cadeia de caracteres para incluir chaves no texto de saída. Vários $ caracteres indicam quantas chaves consecutivas iniciam e terminam a interpolação:

var location = $$"""
   You are at {{{Longitude}}, {{Latitude}}}
   """;

O exemplo anterior especifica que duas chaves iniciam e terminam uma interpolação. A terceira chave de abertura e fechamento repetida é incluída na cadeia de caracteres de saída.

Você pode aprender mais sobre literais de cadeia de caracteres brutos no artigo sobre cadeias de caracteres no guia de programação e os artigos de referência de linguagem sobre literais de cadeia de caracteres e cadeias de caracteres interpoladas.

Estrutura padrão automática

O compilador C# 11 garante que todos os campos de um struct tipo sejam inicializados com seu valor padrão como parte da execução de um construtor. Essa alteração significa que qualquer campo ou propriedade automática não inicializada por um construtor é automaticamente inicializada pelo compilador. Structs onde o construtor não atribui definitivamente todos os campos agora compilados, e todos os campos não explicitamente inicializados são definidos como seu valor padrão. Você pode ler mais sobre como essa alteração afeta a inicialização de struct no artigo sobre structs.

Correspondência Span<char> de padrão ou ReadOnlySpan<char> em uma constante string

Você pôde testar se um string tinha um valor constante específico usando a correspondência de padrões para várias versões. Agora, você pode usar a mesma lógica de correspondência de padrões com variáveis que são Span<char> ou ReadOnlySpan<char>.

Nome alargado do âmbito de aplicação

Nomes de parâmetros de tipo e nomes de parâmetros agora estão no escopo quando usados em uma nameof expressão em uma declaração de atributo nesse método. Esse recurso significa que você pode usar o nameof operador para especificar o nome de um parâmetro de método em um atributo na declaração de método ou parâmetro. Esse recurso geralmente é útil para adicionar atributos para análise anulável.

Literais de cadeia UTF-8

Você pode especificar o sufixo u8 em um literal de cadeia de caracteres para especificar a codificação de caracteres UTF-8. Se seu aplicativo precisa de cadeias de caracteres UTF-8, para constantes de cadeia HTTP ou protocolos de texto semelhantes, você pode usar esse recurso para simplificar a criação de cadeias de caracteres UTF-8.

Você pode saber mais sobre literais de cadeia UTF-8 na seção literal de cadeia de caracteres do artigo sobre tipos de referência internos.

Membros obrigatórios

Você pode adicionar o required modificador a propriedades e campos para impor construtores e chamadores para inicializar esses valores. O System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute pode ser adicionado aos construtores para informar o compilador que um construtor inicializa todos os membros necessários.

Para obter mais informações sobre os membros necessários, consulte a seção somente inicialização do artigo de propriedades.

ref Campos e ref scoped variáveis

Você pode declarar ref campos dentro de um ref structarquivo . Isso suporta tipos como System.Span<T> sem atributos especiais ou tipos internos ocultos.

Você pode adicionar o scoped modificador a qualquer ref declaração. Isso limita o escopo para onde a referência pode escapar.

Tipos locais de arquivo

A partir do C# 11, você pode usar o modificador de file acesso para criar um tipo cuja visibilidade tem como escopo o arquivo de origem no qual ele é declarado. Esse recurso ajuda os autores do gerador de código-fonte a evitar colisões de nomes. Você pode saber mais sobre esse recurso no artigo sobre tipos de escopo de arquivo na referência de idioma.

Consulte também