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# 14 inclui os novos recursos a seguir. Você pode experimentar esses recursos usando a versão mais recente do Visual Studio 2026 ou o SDK do .NET 10:
- Membros de extensão
- Atribuição condicional nula
-
nameofdá suporte a tipos genéricos não associados -
Conversões mais implícitas para
Span<T>eReadOnlySpan<T> - Modificadores em parâmetros lambda simples
-
Propriedades com suporte de
field -
eventos e construtores
partial - Operadores de atribuição composta definidos pelo usuário
- novas diretivas de pré-processador para aplicativos baseados em arquivo
O C# 14 é a versão mais recente do C#. O C# 14 tem suporte no .NET 10. Para obter mais informações, confira Controle de versão da linguagem C#.
Você pode baixar o SDK do .NET 10 mais recente na página de downloads do .NET. Você também pode baixar o Visual Studio 2026, que inclui o SDK do .NET 10.
Você encontra alterações interruptivas introduzidas no C# 14 em nosso artigo sobre alterações interruptivas.
Observação
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.
Membros de extensão
O C# 14 adiciona uma nova sintaxe para definir membros de extensão. A nova sintaxe permite que você declare propriedades de extensão além dos métodos de extensão. Você também pode declarar membros de extensão que estendem o tipo, em vez de uma instância do tipo. Em outras palavras, esses novos membros de extensão podem aparecer como membros estáticos do tipo que você estende. Essas extensões podem incluir operadores definidos pelo usuário implementados como métodos de extensão estáticos. O exemplo de código a seguir mostra um exemplo dos diferentes tipos de membros de extensão que você pode declarar:
public static class Enumerable
{
// Extension block
extension<TSource>(IEnumerable<TSource> source) // extension members for IEnumerable<TSource>
{
// Extension property:
public bool IsEmpty => !source.Any();
// Extension method:
public IEnumerable<TSource> Where(Func<TSource, bool> predicate) { ... }
}
// extension block, with a receiver type only
extension<TSource>(IEnumerable<TSource>) // static extension members for IEnumerable<Source>
{
// static extension method:
public static IEnumerable<TSource> Combine(IEnumerable<TSource> first, IEnumerable<TSource> second) { ... }
// static extension property:
public static IEnumerable<TSource> Identity => Enumerable.Empty<TSource>();
// static user defined operator:
public static IEnumerable<TSource> operator + (IEnumerable<TSource> left, IEnumerable<TSource> right) => left.Concat(right);
}
}
Os membros no primeiro bloco de extensão são chamados como se fossem membros da instância de IEnumerable<TSource>, por exemplo sequence.IsEmpty. Os membros no segundo bloco de extensão são chamados como se fossem membros estáticos de IEnumerable<TSource>, por exemplo IEnumerable<int>.Identity.
Você pode saber mais detalhes lendo o artigo sobre membros de extensão no guia de programação, o artigo de referência de idioma sobre a extension palavra-chave e a especificação do novo recurso de membros de extensão.
A palavra-chave field
O token field permite que você escreva o corpo de um acessador de propriedade sem declarar um campo de apoio explícito. O token field é substituído por um campo de backup sintetizado pelo compilador.
Por exemplo, no passado, se você quisesse garantir que uma string propriedade não pudesse ser definida para null, você teria que declarar um campo de apoio e implementar ambos os métodos de acesso.
private string _msg;
public string Message
{
get => _msg;
set => _msg = value ?? throw new ArgumentNullException(nameof(value));
}
Agora você pode simplificar seu código para:
public string Message
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}
Você pode declarar um corpo para um ou ambos os acessadores de uma propriedade de campo.
Há uma possível alteração incompatível ou confusão ao ler código em tipos que também incluem um símbolo chamado field. Você pode usar @field ou this.field desambiguar entre a field palavra-chave e o identificador ou renomear o símbolo atual field para fornecer melhor distinção.
Conversões de intervalo implícitas
O C# 14 apresenta suporte de primeira classe para System.Span<T> e System.ReadOnlySpan<T> no idioma. Esse suporte envolve novas conversões implícitas que permitem uma programação mais natural com esses tipos.
Span<T> e ReadOnlySpan<T> são usados de várias maneiras principais em C# e no runtime. Sua introdução melhora o desempenho sem arriscar a segurança. O C# 14 reconhece a relação e dá suporte a algumas conversões entre ReadOnlySpan<T>, Span<T>e T[]. Os tipos de alcance podem ser receptores de métodos de extensão, se compor com outras conversões e auxiliar em cenários de inferência de tipo genérico.
Você pode encontrar a lista de conversões implícitas de span no artigo sobre tipos internos na seção de referência da linguagem. Você pode saber mais detalhes lendo a especificação da funcionalidade para tipos de segmento de primeira classe.
Tipos genéricos não associados e nameof
A partir do C# 14, o argumento de nameof pode ser um tipo genérico não vinculado. Por exemplo, nameof(List<>) é avaliado como List. Em versões anteriores do C#, somente tipos genéricos fechados, como List<int>, poderiam ser usados para retornar o List nome.
Parâmetros lambda simples com modificadores
Você pode adicionar modificadores de parâmetro, como scoped, ref, in, outou ref readonly a parâmetros de expressão lambda sem especificar o tipo de parâmetro:
delegate bool TryParse<T>(string text, out T result);
// ...
TryParse<int> parse1 = (text, out result) => Int32.TryParse(text, out result);
Anteriormente, a adição de modificadores só era permitida quando as declarações de parâmetro incluíam os tipos para os parâmetros. A declaração anterior exigiria tipos em todos os parâmetros:
TryParse<int> parse2 = (string text, out int result) => Int32.TryParse(text, out result);
O params modificador ainda requer uma lista de parâmetros explicitamente tipada.
Você pode ler mais sobre essas alterações no artigo sobre expressões lambda na referência de linguagem C#.
Membros com mais parcialidade
Agora você pode declarar construtores de instância e eventos como membros parciais.
Construtores parciais e eventos parciais devem incluir exatamente uma declaração de definição e uma declaração de implementação.
Somente a declaração de implementação de um construtor parcial pode incluir um inicializador de construtor: this() ou base(). Somente uma declaração de tipo parcial pode incluir a sintaxe do construtor primário.
A declaração de implementação de um evento parcial deve incluir os acessadores add e remove. A declaração de definição declara um evento semelhante a um campo.
Atribuição composta definida pelo usuário
Saiba mais na especificação do recurso para atribuição composta definida pelo usuário.
Atribuição condicional nula
Os operadores de acesso a membros com condição nula, ?. e ?[], podem agora ser usados no lado esquerdo de uma atribuição ou atribuição composta.
Antes do C# 14, você precisava verificar se uma variável é nula antes de atribuir a uma propriedade.
if (customer is not null)
{
customer.Order = GetCurrentOrder();
}
Você pode simplificar o código anterior usando o ?. operador:
customer?.Order = GetCurrentOrder();
O lado direito do = operador é avaliado somente quando o lado esquerdo não é nulo. Se customer for nulo, o código não chamará GetCurrentOrder.
Além da atribuição, você pode usar operadores de acesso de membro condicional nulo com operadores de atribuição composta (+=, -= e outros). No entanto, incrementar e diminuir, ++ e --não são permitidos.
Saiba mais no artigo de referência de idioma sobre o acesso condicional ao membro e a especificação de recurso para atribuição condicional nula.