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# 15 inclui os novos recursos a seguir. Experimente esses recursos usando a versão mais recente do Visual Studio 2026 insiders ou o SDK de versão prévia do .NET 11:
O C# 15 é a versão prévia mais recente do C#. As versões prévias do .NET 11 dão suporte ao C# 15. Para obter mais informações, confira Controle de versão da linguagem C#.
Você pode baixar o SDK de versão prévia mais recente do .NET 11 na página de downloads do .NET. Você também pode baixar o Visual Studio 2026, que inclui o SDK de versão preliminar do .NET 11.
A página "Novidades em C#" adiciona novos recursos quando eles estão disponíveis em versões de visualização pública. A seção conjunto de trabalho da página de status do recurso roslyn acompanha quando os recursos futuros são mesclados na ramificação principal.
Você encontra alterações interruptivas introduzidas no C# 15 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.
Argumentos de expressão de coleção
Você pode passar argumentos para o construtor ou o método de fábrica da coleção subjacente usando um with(...) elemento como o primeiro elemento em uma expressão de coleção. Esse recurso permite que você especifique capacidade, comparadores ou outros parâmetros de construtor diretamente dentro da sintaxe da expressão de coleção.
O exemplo a seguir mostra como passar um argumento de capacidade para um List<T> construtor e um comparador para um HashSet<T>:
string[] values = ["one", "two", "three"];
// Pass capacity argument to List<T> constructor
List<string> names = [with(capacity: values.Length * 2), .. values];
// Pass comparer argument to HashSet<T> constructor
HashSet<string> set = [with(StringComparer.OrdinalIgnoreCase), "Hello", "HELLO", "hello"];
// set contains only one element because all strings are equal with OrdinalIgnoreCase
Para saber mais sobre argumentos de expressão de coleção, consulte o artigo de referência de linguagem sobre expressões de coleção ou a especificação de recurso. Para obter informações sobre como usar argumentos de expressão de coleção em inicializadores de coleção, consulte Inicializadores de Objeto e Coleção.
Tipos de união
O C# 15 apresenta tipos de união, que representam um valor que pode ser um dos vários tipos de casos. Declare uma união com a union palavra-chave:
public record class Cat(string Name);
public record class Dog(string Name);
public record class Bird(string Name);
public union Pet(Cat, Dog, Bird);
As uniões fornecem conversões implícitas de cada tipo de caso e o compilador garante que as expressões switch sejam exaustivas em todos os tipos de casos:
Pet pet = new Dog("Rex");
string name = pet switch
{
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};
O runtime inclui os tipos UnionAttribute e IUnion começando com .NET 11 Versão Prévia 5. Alguns recursos da especificação da proposta ainda não foram implementados. Esses recursos estão chegando em versões prévias futuras.
Para obter mais informações, consulte Tipos de união na referência da linguagem ou na especificação do recurso.
Hierarquias fechadas
A partir do C# 15, você pode aplicar o closed modificador a uma classe para declarar uma hierarquia fechada. Uma classe fechada só pode ser derivada de dentro do assembly em que foi declarada, o que fixa o conjunto de descendentes diretos em tempo de compilação:
public closed record class GateState;
public record class Closed : GateState;
public record class Open(float Percent) : GateState;
Como o compilador conhece cada descendente direto, uma expressão que manipula cada um switch deles é exaustiva e não precisa de um braço padrão:
string Describe(GateState state) => state switch
{
Closed => "closed",
Open(var percent) => $"{percent}% open",
// No warning: every direct descendant of 'GateState' is handled.
};
O closed modificador é uma palavra-chave contextual. Uma closed classe é implicitamente abstract e não pode ser combinada com sealed, staticou um modificador explícito abstract . A derivação não é transitiva: um descendente não fechado de uma classe fechada ainda pode ser derivado de outros assemblies. Para estender a verificação de exaustividade ao longo da hierarquia, marque também os descendentes intermediários closed.
Observação
No C# 15 versão preliminar 5, o runtime ainda não inclui System.Runtime.CompilerServices.ClosedAttribute. Até que ele faça isso, cada projeto que usa o closed modificador deve declarar o próprio atributo:
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class ClosedAttribute : Attribute { }
Para obter mais informações, consulte o modificador closed e os padrões de hierarquia fechada, na referência da linguagem, ou a especificação do recurso. Você pode copiar os exemplos desta seção, incluindo a solução alternativa ClosedAttribute, do projeto keywords snippets no repositório dotnet/docs do GitHub.
Segurança de memória
O C# 15 inicia um esforço de várias versões para redefinir a segurança da memória na linguagem. O objetivo é vincular o contexto unsafe às operações que realmente acessam memória não gerenciada, em vez de à existência de tipos de ponteiro. A maioria das vulnerabilidades de segurança de memória vem dessas operações de acesso, portanto, o idioma faz com que elas se destaquem para revisores e auditores.
No modelo completo, unsafe em um membro o marca como requires-unsafe: a obrigação de auditoria é transferida ao chamador, que deve usar o membro em um contexto unsafe. Um assembly adere a essa imposição, e o compilador registra a escolha com o atributo System.Runtime.CompilerServices.MemorySafetyRulesAttribute. O modelo também adiciona uma palavra-chave contextual safe que marca membros e campos de layout explícito extern como seguros. Juntas, essas regras tornam explícitos os limites da não segurança de memória potencial em um programa.
A primeira etapa inclui os relaxamentos do ponteiro. Quando você compila com a versão do preview idioma, as seguintes operações não exigem mais um unsafe contexto:
- Declarando um tipo de ponteiro e tomando o endereço de uma variável com o
&operador. - A
fixeddeclaração, que fixa uma variável. - Convertendo uma
stackallocexpressão em um ponteiro. - O operador
sizeofaplicado a qualquer tipo não gerenciado.
O exemplo a seguir cria e fixa um ponteiro sem um contexto unsafe:
int number = 42;
int* pointer = &number;
int[] numbers = [10, 20, 30];
fixed (int* first = numbers)
{
// Dereferencing the pointer still requires an unsafe context.
}
As operações que acessam a memória apontada, como indireção de ponteiro (*p), acesso a membro de ponteiro (p->member), acesso a elemento de ponteiro (p[i]) e invocação de ponteiro de função, ainda exigem um contexto unsafe.
O modelo de membro requires-unsafe, a adesão do assembly às regras atualizadas de segurança da memória e a palavra-chave contextual safe estarão disponíveis em uma versão prévia posterior.
Para obter mais informações, consulte código não seguro, tipos de ponteiro e ponteiros de função na referência de idioma ou na especificação do recurso.