Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
C# 15 bevat de volgende nieuwe functies. Probeer deze functies met behulp van de nieuwste versie van Visual Studio 2026 insiders of de .NET 11 preview-SDK:
- Argumenten voor verzamelingsexpressie
- Samenvoegtypen
- Gesloten hiërarchieën
- Indexeerders voor uitbreidingen
- Geheugenveiligheid
C# 15 is de nieuwste C#-preview-versie. .NET 11 preview-versies ondersteunen C# 15. Zie C#-taalversiebeheer voor meer informatie.
U kunt de nieuwste .NET 11 preview-SDK downloaden via de .NET-downloadpagina. U kunt ook Visual Studio 2026-insiders downloaden, waaronder de .NET 11 preview-SDK.
Op de pagina 'Wat is er nieuw in C#' worden nieuwe functies toegevoegd wanneer deze beschikbaar zijn in openbare preview-versies. In de werksetsectie van de Roslyn-functiestatuspagina wordt bijgehouden wanneer toekomstige functies worden samengevoegd in de hoofdbranch.
U vindt alle belangrijke wijzigingen die zijn geïntroduceerd in C# 15 in ons artikel over belangrijke wijzigingen.
Opmerking
We zijn geïnteresseerd in uw feedback over deze functies. Als u problemen ondervindt met een van deze nieuwe functies, maakt u een nieuw probleem in de dotnet-/roslyn-opslagplaats .
Argumenten voor verzamelingsexpressie
U kunt argumenten doorgeven aan de constructor of factory-methode van de onderliggende verzameling met behulp van een with(...) element als het eerste element in een verzamelingsexpressie. Met deze functie kunt u capaciteit, vergelijkingsparameters of andere constructorparameters rechtstreeks in de syntaxis van de verzamelingsexpressie opgeven.
In het volgende voorbeeld ziet u hoe u een capaciteitsargument doorgeeft aan een List<T> constructor en een vergelijkingsfunctie met een 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
Zie het taalreferentieartikel over verzamelingsexpressies of de functiespecificatie voor meer informatie over argumenten voor verzamelingsexpressies. Zie Initializers voor objecten en verzamelingen voor informatie over het gebruik van argumenten voor verzamelingexpressies in initialisatiefuncties voor verzamelingen.
Uniontypen
C# 15 introduceert samenvoegtypen, die een waarde vertegenwoordigen die een van de verschillende casetypen kan zijn. Declareer een samenvoeging met het union trefwoord:
public record class Cat(string Name);
public record class Dog(string Name);
public record class Bird(string Name);
public union Pet(Cat, Dog, Bird);
Unions bieden impliciete conversies van elk casetype, en de compiler zorgt ervoor dat switch expressies uitputtend zijn over alle casetypen.
Pet pet = new Dog("Rex");
string name = pet switch
{
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};
De runtime bevat de typen UnionAttribute en IUnion vanaf .NET 11 preview 5. Sommige functies uit de voorstelspecificatie zijn nog niet geïmplementeerd. Deze functies zijn beschikbaar in toekomstige previews.
Zie Union-typen in de taalreferentie of de functiespecificatie voor meer informatie.
Gesloten hiërarchieën
Vanaf C# 15 kunt u de closed wijzigingsfunctie toepassen op een klasse om een gesloten hiërarchie te declareren. Van een gesloten klasse kan alleen worden overgeërfd binnen de assembly waarin deze is gedeclareerd, waarmee de verzameling directe subklassen tijdens het compileren wordt vastgelegd:
public closed record class GateState;
public record class Closed : GateState;
public record class Open(float Percent) : GateState;
Omdat de compiler elke directe afstammeling kent, is een switch expressie die elke afhandelt volledig en heeft geen standaardarm nodig:
string Describe(GateState state) => state switch
{
Closed => "closed",
Open(var percent) => $"{percent}% open",
// No warning: every direct descendant of 'GateState' is handled.
};
De closed wijziging is een contextueel trefwoord. Een closed klasse is impliciet abstract en kan niet worden gecombineerd met sealed, staticof een expliciete abstract wijziging. De afleiding is niet transitief: een niet-gesloten afstammeling van een gesloten klasse kan nog steeds worden afgeleid uit andere assembly's. Als u de volledige controle van de hiërarchie wilt uitbreiden, markeert u ook tussenliggende nakomelingen closed .
Opmerking
In C# 15 preview 5 wordt de runtime nog niet verzonden System.Runtime.CompilerServices.ClosedAttribute. Totdat dit het geval is, moet elk project dat gebruikmaakt van de closed modifier het kenmerk zelf declareren:
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class ClosedAttribute : Attribute { }
Zie de gesloten wijzigings- en gesloten hiërarchiepatronen in de taalverwijzing of de functiespecificatie voor meer informatie. U kunt de voorbeelden in deze sectie kopiëren, inclusief de tijdelijke oplossing ClosedAttribute, vanuit het project keywords-fragmenten in de opslagplaats dotnet/docs GitHub.
Indexeerders voor uitbreidingen
Vanaf C# 15 kunt u indexeerfuncties in een extension blok declareren. Met extensieindexeerfuncties kunt u indexeren in een ontvanger alsof de indexeerfunctie is gedeclareerd voor het ontvangertype. Omdat indexeerfuncties altijd exemplaarleden zijn, moet een extensieblok dat een indexeerfunctie declareert een benoemde ontvangerparameter opgeven.
In het volgende voorbeeld wordt in IEnumerable<int> een indexer met alleen een getter gedeclareerd die het element op een opgegeven positie retourneert:
public static class SequenceIndexer
{
extension(IEnumerable<int> sequence)
{
public int this[int index] => sequence.ElementAt(index);
}
}
U indexeer in de ontvanger alsof de indexeerfunctie lid was van het ontvangertype:
IEnumerable<int> numbers = Enumerable.Range(1, 10);
int third = numbers[2];
Zie Extensiedeclaratie in de taalverwijzing of de functiespecificatie voor meer informatie.
Geheugenveiligheid
C# 15 begint met een multirelease-inspanning om de geheugenveiligheid in de taal opnieuw te definiëren. Het doel is om de unsafe context te koppelen aan de bewerkingen die daadwerkelijk toegang hebben tot onbeheerd geheugen, in plaats van het bestaan van aanwijzertypen. De meeste beveiligingsproblemen in het geheugen zijn afkomstig van deze toegangsbewerkingen, dus de taal maakt ze opvallen voor revisoren en auditors.
In het complete model markeert unsafe op een lid dit als requires-unsafe: de auditverplichting verschuift naar de aanroeper, die het lid vanuit een unsafe-context moet gebruiken. Een assembly kiest voor deze afdwinging en de compiler registreert de keuze met het System.Runtime.CompilerServices.MemorySafetyRulesAttribute kenmerk. Het model voegt ook een safe contextueel trefwoord toe dat extern leden en velden met expliciete indeling als veilig markeert. Samen maken deze regels de grenzen van potentiële geheugenonveiligheid expliciet voor een programma.
De eerste stap omvat de pointerversoepelingen. Wanneer u compileert met de preview taalversie, hebben de volgende bewerkingen geen context meer nodig unsafe :
- Het declareren van een aanwijzertype en het opvragen van het adres van een variabele met de operator
&. - De
fixedinstructie, waarmee een variabele wordt vastgemaakt. -
stackallocEen expressie converteren naar een aanwijzer. - De
sizeof-operator toegepast op elk onbeheerd type.
In het volgende voorbeeld wordt een aanwijzer zonder unsafe context gemaakt en vastgemaakt:
int number = 42;
int* pointer = &number;
int[] numbers = [10, 20, 30];
fixed (int* first = numbers)
{
// Dereferencing the pointer still requires an unsafe context.
}
De bewerkingen die toegang bieden tot het geheugen waarnaar wordt verwezen, zoals pointerindirectie (*p), toegang tot pointerleden (p->member), toegang tot pointerelementen (p[i]) en het aanroepen van functiepointers, vereisen nog steeds een unsafe-context.
Het lidmodel requires-unsafe, de opt-in van assembly’s voor de bijgewerkte regels voor geheugenveiligheid en het contextuele trefwoord safe komen in een latere preview.
Zie Onveilige code, aanwijzertypen en functiewijzers in de taalreferentie of de functiespecificatie voor meer informatie.