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.
Gebruik een verzamelingsexpressie om algemene verzamelingswaarden te maken. Een verzamelingsexpressie is een terse-syntaxis die u kunt toewijzen aan veel verschillende verzamelingstypen. Een verzamelingsexpressie bevat een reeks elementen tussen [ haakjes ] .
De C#-taalreferentiedocumenten beschrijven de meest recent uitgebrachte versie van de C#-taal. Het bevat ook de eerste documentatie voor functies in openbare previews voor de aanstaande taalrelease.
De documentatie identificeert alle functies die voor het eerst zijn geïntroduceerd in de laatste drie versies van de taal of in de huidige openbare previews.
Aanbeveling
Raadpleeg het artikel over de versiegeschiedenis van de C#-taal om te achterhalen wanneer een functie voor het eerst is geïntroduceerd in C#.
In het volgende voorbeeld worden elementen System.Span<T>string declareren en geïnitialiseerd tot de dagen van de week:
Span<string> weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
foreach (var day in weekDays)
{
Console.WriteLine(day);
}
U kunt een verzamelingsexpressie converteren naar veel verschillende verzamelingstypen. In het eerste voorbeeld werd gedemonstreerd hoe u een variabele initialiseert met behulp van een verzamelingsexpressie. De volgende code toont veel van de andere locaties waar u een verzamelingsexpressie kunt gebruiken:
// Initialize private field:
private static readonly ImmutableArray<string> _months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// property with expression body:
public IEnumerable<int> MaxDays =>
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
public int Sum(IEnumerable<int> values) =>
values.Sum();
public void Example()
{
// As a parameter:
int sum = Sum([1, 2, 3, 4, 5]);
}
U kunt geen verzamelingsexpressie gebruiken waarbij een compilatieconstante wordt verwacht, zoals bij het initialiseren van een constante of als de standaardwaarde voor een methodeargument.
In beide vorige voorbeelden zijn constanten gebruikt als de elementen van een verzamelingsexpressie. U kunt ook variabelen voor de elementen gebruiken, zoals wordt weergegeven in het volgende voorbeeld:
string hydrogen = "H";
string helium = "He";
string lithium = "Li";
string beryllium = "Be";
string boron = "B";
string carbon = "C";
string nitrogen = "N";
string oxygen = "O";
string fluorine = "F";
string neon = "Ne";
string[] elements = [hydrogen, helium, lithium, beryllium, boron, carbon, nitrogen, oxygen, fluorine, neon];
foreach (var element in elements)
{
Console.WriteLine(element);
}
Verspreid element
Gebruik een verspreid element.. om inlineverzamelingswaarden in een verzamelingsexpressie te gebruiken. In het volgende voorbeeld wordt een verzameling voor het volledige alfabet gemaakt door een verzameling klinkers, een verzameling van de medeklinkers en de letter 'y' te combineren. Dit kan een van de volgende zijn:
string[] vowels = ["a", "e", "i", "o", "u"];
string[] consonants = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "z"];
string[] alphabet = [.. vowels, .. consonants, "y"];
Het verspreide element ..vowels, wanneer geëvalueerd, produceert vijf elementen: "a", "e", "i", "o"en "u". Het verspreide element ..consonants produceert 20 elementen, het getal in de consonants matrix. De expressie in een spread-element moet worden opgesomd met behulp van een foreach instructie. Zoals u in het vorige voorbeeld kunt zien, kunt u verspreide elementen combineren met afzonderlijke elementen in een verzamelingsexpressie.
Conversies
U kunt een verzamelingsexpressie converteren naar verschillende verzamelingstypen, waaronder:
- System.Span<T> en System.ReadOnlySpan<T>.
-
Matrices, zoals
int[]ofstring[]. - Elk type met een create-methode waarvan het parametertype is
ReadOnlySpan<T>waar een impliciete conversie is van het type verzamelingsexpressie naarT. - Elk type dat ondersteuning biedt voor een initialisatiefunctie voor verzamelingen Deze vereiste betekent meestal dat het type ondersteuning biedt System.Collections.Generic.IEnumerable<T> en dat er een toegankelijke
Addmethode is om items toe te voegen aan de verzameling. Er moet een impliciete conversie zijn van het type expressie-elementen van de verzameling naar het elementtype van de verzameling. Voor verspreide elementen moet er een impliciete conversie zijn van het type van het spread-element naar het elementtype van de verzameling. - Een van de volgende interfaces:
Opmerking
U kunt verzamelingsexpressies niet gebruiken om inlinematrices te initialiseren. Voor inlinematrices zijn verschillende initialisatiesyntaxis vereist.
Belangrijk
Een verzamelingexpressie maakt altijd een verzameling die alle elementen in de verzamelingsexpressie bevat, ongeacht het doeltype van de conversie. Wanneer het doel van de conversie bijvoorbeeld is System.Collections.Generic.IEnumerable<T>, evalueert de gegenereerde code de verzamelingsexpressie en slaat de resultaten op in een in-memory verzameling.
Dit gedrag verschilt van LINQ, waarbij een reeks mogelijk pas wordt geïnstantieerd nadat deze is geïnventariseerd. U kunt geen verzamelingsexpressies gebruiken om een oneindige reeks te genereren die niet wordt geïnventariseerd.
De compiler maakt gebruik van statische analyse om de meest presterende manier te bepalen om de verzameling te maken die is gedeclareerd met een verzamelingsexpressie. De lege verzamelingsexpressie, []kan bijvoorbeeld worden gerealiseerd Array.Empty<T>() alsof het doel niet wordt gewijzigd na initialisatie. Wanneer het doel een System.Span<T> of System.ReadOnlySpan<T>is, kan de opslag worden gestapeld. In de functiespecificatie voor verzamelingsexpressies worden de regels opgegeven die de compiler moet volgen.
Veel API's zijn overbelast met meerdere verzamelingstypen als parameters. Omdat een verzamelingsexpressie kan worden geconverteerd naar veel verschillende expressietypen, vereisen deze API's mogelijk casts op de verzamelingsexpressie om de juiste conversie op te geven. Met de volgende conversieregels worden enkele dubbelzinnigheden opgelost:
- Een betere elementconversie heeft de voorkeur boven een betere conversie van verzamelingstypen. Met andere woorden, het type elementen in de verzamelingsexpressie heeft meer belang dan het type verzameling. Deze regels worden beschreven in de functiespecificatie voor een betere conversie van verzamelingsexpressie.
- Conversie naar Span<T>, ReadOnlySpan<T>of een ander
ref structtype is beter dan een conversie naar een niet-refstructtype. - Conversie naar een niet-interfacetype is beter dan een conversie naar een interfacetype.
Wanneer u een verzamelingsexpressie converteert naar een Span of ReadOnlySpan, is de veilige context van het spanobject afkomstig van de veilige context van alle elementen die in de periode zijn opgenomen. Zie de specificatie van de verzamelingsexpressie voor gedetailleerde regels.
Opbouwfunctie voor verzamelingen
Verzamelingsexpressies werken met elk verzamelingstype dat goed werkt. Een goed gedragen verzameling heeft de volgende kenmerken:
- De waarde van
CountofLengthop een aftelbare verzameling produceert dezelfde waarde als het aantal elementen dat wordt opgesomd. - De typen in de System.Collections.Generic naamruimte zijn neveneffectvrij. De compiler kan scenario's optimaliseren waarbij deze typen kunnen worden gebruikt als intermediaire waarden, maar anders worden ze niet weergegeven.
- Een aanroep van een toepasselijk
.AddRange(x)lid in een verzameling resulteert in dezelfde uiteindelijke waarde als het herhalenxen toevoegen van alle geïnventareerde waarden afzonderlijk aan de verzameling met behulp van.Add.
Alle verzamelingstypen in de .NET-runtime werken goed.
Waarschuwing
Als een aangepast verzamelingstype niet goed werkt, is het gedrag niet gedefinieerd wanneer u dat verzamelingstype gebruikt met verzamelingsexpressies.
Uw typen melden zich aan voor ondersteuning voor verzamelingsexpressies door een Create() methode te schrijven en het System.Runtime.CompilerServices.CollectionBuilderAttribute kenmerk toe te passen op het verzamelingstype om de opbouwmethode aan te geven. Denk bijvoorbeeld aan een toepassing die gebruikmaakt van buffers met vaste lengte van 80 tekens. Deze klasse kan er ongeveer als volgt uitzien:
public class LineBuffer : IEnumerable<char>
{
private readonly char[] _buffer;
private readonly int _count;
public LineBuffer(ReadOnlySpan<char> buffer)
{
_buffer = new char[buffer.Length];
_count = buffer.Length;
for (int i = 0; i < _count; i++)
{
_buffer[i] = buffer[i];
}
}
public int Count => _count;
public char this[int index]
{
get
{
if (index >= _count)
throw new IndexOutOfRangeException();
return _buffer[index];
}
}
public IEnumerator<char> GetEnumerator()
{
for (int i = 0; i < _count; i++)
{
yield return _buffer[i];
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
// etc
}
U wilt deze gebruiken met verzamelingexpressies, zoals wordt weergegeven in het volgende voorbeeld:
LineBuffer line = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'];
Het LineBuffer type implementeert IEnumerable<char>, zodat de compiler het herkent als een verzameling char items. De typeparameter van de geïmplementeerde System.Collections.Generic.IEnumerable<T> interface geeft het elementtype aan. U moet twee toevoegingen aan uw toepassing maken om verzamelingsexpressies toe te wijzen aan een LineBuffer object. Eerst moet u een klasse maken die een Create methode bevat:
internal static class LineBufferBuilder
{
internal static LineBuffer Create(ReadOnlySpan<char> values) => new LineBuffer(values);
}
De Create methode moet een LineBuffer object retourneren en moet een laatste parameter van het type ReadOnlySpan<char>hebben. De typeparameter van de ReadOnlySpan verzameling moet overeenkomen met het elementtype van de verzameling. Een opbouwmethode die een algemene verzameling retourneert, heeft de algemene ReadOnlySpan<T> als parameter. De methode moet toegankelijk zijn en static.
Vanaf C# 15 kan de Create methode extra parameters hebben vóór de ReadOnlySpan<T> parameter. U kunt waarden doorgeven aan deze parameters met behulp van een with(...) element in de verzamelingsexpressie. Zie argumenten voor de opbouwfunctie voor verzamelingen voor meer informatie.
Ten slotte moet u de declaratie van de CollectionBuilderAttributeLineBuffer klasse toevoegen:
[CollectionBuilder(typeof(LineBufferBuilder), "Create")]
De eerste parameter bevat de naam van de Builder-klasse . Het tweede kenmerk bevat de naam van de opbouwmethode.
Argumenten voor verzamelingsexpressie
Vanaf C# 15 kunt u 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. Zie de functiespecificatie voor verzamelingsexpressies voor meer informatie.
Het with(...) element moet het eerste element in de verzamelingsexpressie zijn. De argumenten die in het with(...) element worden gedeclareerd, worden doorgegeven aan de juiste constructor of maakmethode op basis van het doeltype. U kunt elke geldige expressie gebruiken voor de argumenten in het with element.
Constructorargumenten
Wanneer het doeltype een klasse of struct is die wordt geïmplementeerd System.Collections.IEnumerable, worden de argumenten in with(...) geëvalueerd en worden de resultaten doorgegeven aan de constructor. De compiler gebruikt overbelastingsresolutie om de best overeenkomende constructor te selecteren:
public void CollectionArgumentsExamples()
{
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
// Pass capacity to IList<T> (uses List<T> constructor)
IList<int> numbers = [with(capacity: 100), 1, 2, 3];
}
In het voorgaande voorbeeld:
- De
List<string>constructor met eencapacityparameter wordt aangeroepen metvalues.Length * 2. - De
HashSet<string>constructor met een System.Collections.Generic.IEqualityComparer<T> parameter wordt aangeroepen metStringComparer.OrdinalIgnoreCase. - Voor interfacedoeltypen zoals System.Collections.Generic.IList<T>, maakt de compiler een
List<T>met de opgegeven capaciteit.
Argumenten voor opbouwfunctie voor verzamelingen
Voor typen met een System.Runtime.CompilerServices.CollectionBuilderAttribute, worden de argumenten die in het with(...) element zijn gedeclareerd, geëvalueerd en worden de resultaten doorgegeven aan de create-methode vóór de ReadOnlySpan<T> parameter. Met deze functie kunt u methoden maken om configuratieparameters te accepteren:
internal static class MySetBuilder
{
internal static MySet<T> Create<T>(ReadOnlySpan<T> items) => new MySet<T>(items);
internal static MySet<T> Create<T>(IEqualityComparer<T> comparer, ReadOnlySpan<T> items) =>
new MySet<T>(items, comparer);
}
Vervolgens kunt u het with(...) element gebruiken om de vergelijking door te geven:
public void CollectionBuilderArgumentsExample()
{
// Pass comparer to a type with CollectionBuilder attribute
// The comparer argument is passed before the ReadOnlySpan<T> parameter
MySet<string> mySet = [with(StringComparer.OrdinalIgnoreCase), "A", "a", "B"];
// mySet contains only two elements: "A" and "B"
}
De methode voor maken wordt geselecteerd met overbelastingsresolutie op basis van de opgegeven argumenten. Het ReadOnlySpan<T> bevat de verzamelingselementen is altijd de laatste parameter.
Doeltypen van interface
Verschillende interfacedoeltypen ondersteunen expressieargumenten voor verzamelingen. In de volgende tabel ziet u de ondersteunde interfaces en de bijbehorende constructorhandtekeningen:
| gebruikersinterface | Ondersteunde with elementen |
|---|---|
| IEnumerable<T>, IReadOnlyCollection<T>IReadOnlyList<T> |
() (alleen leeg) |
| ICollection<T>, IList<T> |
(), (int capacity) |
Voor IList<T> en ICollection<T>gebruikt de compiler een System.Collections.Generic.List<T> met de opgegeven constructor.
Beperkingen
Het with(...) element heeft de volgende beperkingen:
- Dit moet het eerste element in de verzamelingsexpressie zijn.
- Argumenten kunnen geen type hebben
dynamic. - Dit wordt niet ondersteund voor matrices of spantypen (
Span<T>,ReadOnlySpan<T>).