Gyűjteménykifejezések – C# nyelvi referencia
Gyűjteménykifejezéssel közös gyűjteményértékeket hozhat létre. A gyűjteménykifejezések olyan terse szintaxisok, amelyek kiértékelésekor számos különböző gyűjteménytípushoz rendelhetők. A gyűjteménykifejezések elemek sorozatát tartalmazzák a zárójelek és ]
a zárójelek között[
. Az alábbi példa egy elemeket System.Span<T>string
deklarál, és inicializálja őket a hét napjaira:
Span<string> weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
foreach (var day in weekDays)
{
Console.WriteLine(day);
}
A gyűjteménykifejezések számos különböző gyűjteménytípusra konvertálhatók. Az első példa bemutatja, hogyan inicializálhat egy változót gyűjteménykifejezéssel. Az alábbi kód számos más helyet mutat be, ahol gyűjteménykifejezést használhat:
// 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]);
}
Nem használhat olyan gyűjteménykifejezést, amelyben fordítási időállandót várnak, például inicializálhat egy állandót, vagy egy metódusargumentum alapértelmezett értékeként.
Mindkét előző példa konstansokat használt egy gyűjteménykifejezés elemeiként. Az elemekhez változókat is használhat az alábbi példában látható módon:
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);
}
Oldalpár elem
A gyűjteménykifejezések beágyazott gyűjteményértékeivel egy oldalpár elemet..
használ. Az alábbi példa létrehoz egy gyűjteményt a teljes ábécé számára a magánhangzók gyűjteményének, a mássalhangzók gyűjteményének és az "y" betűnek a kombinálásával, amely a következő lehet:
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"];
Az oldalpárelem ..vowels
kiértékelésekor öt elemet hoz létre: "a"
, "e"
, "i"
, "o"
és "u"
. Az oldalpár ..consonants
20 elemet állít elő, a tömbben lévő consonants
számot. Az eloszláselem változójának számba kell vennie egy foreach
utasítással. Ahogy az előző példában is látható, az oldalpár elemeit egyesítheti a gyűjteménykifejezések egyes elemeivel.
Konverziók
A gyűjteménykifejezések különböző gyűjteménytípusokká konvertálhatók, például:
- System.Span<T> és System.ReadOnlySpan<T>.
- Tömbök.
- Bármely olyan létrehozási metódussal rendelkező típus, amelynek paramétertípusa
ReadOnlySpan<T>
az, ahol implicit átalakítás történik a gyűjteménykifejezés típusától a következőreT
: . - Bármely olyan típus, amely támogatja a gyűjtemény inicializálóját, például System.Collections.Generic.List<T>. Ez a követelmény általában azt jelenti, hogy a típus támogatja System.Collections.Generic.IEnumerable<T> a típust, és van egy akadálymentes
Add
módszer az elemek gyűjteményhez való hozzáadására. Implicit átalakításnak kell lennie a gyűjteménykifejezés elemeinek típusából a gyűjtemény elemtípusára. Az oldalpárelemek esetében implicit átalakításnak kell lennie az oldalpárelem típusából a gyűjtemény elemtípusára. - Az alábbi felületek bármelyike:
Fontos
A gyűjteménykifejezések mindig létrehoznak egy gyűjteményt, amely a gyűjteménykifejezés összes elemét tartalmazza, függetlenül az átalakítás céltípusától. Ha például az átalakítás System.Collections.Generic.IEnumerable<T>célja, a generált kód kiértékeli a gyűjteménykifejezést, és egy memórián belüli gyűjteményben tárolja az eredményeket.
Ez a viselkedés különbözik a LINQ-tól, ahol előfordulhat, hogy a sorozat nem lesz példányosítva, amíg meg nem történik a számbavétele. Gyűjteménykifejezésekkel nem hozhat létre olyan végtelen sorozatot, amely nem lesz számba vehető.
A fordító statikus elemzéssel határozza meg a gyűjtemény gyűjteménykifejezéssel deklarált létrehozásának leghatékonyabb módját. Az üres gyűjteménykifejezés például úgy valósítható meg, []
mintha Array.Empty<T>() a cél nem módosul az inicializálás után. Ha a cél egy System.Span<T> vagy System.ReadOnlySpan<T>, a tárolót lehet lefoglalni. A gyűjteménykifejezések funkciós specifikációja meghatározza, hogy a fordítónak mely szabályokat kell követnie.
Számos API paraméterként több gyűjteménytípussal van túlterhelve. Mivel a gyűjteménykifejezések számos különböző kifejezéstípusra konvertálhatók, előfordulhat, hogy ezek az API-k megkövetelik a gyűjteménykifejezésen a megfelelő átalakítás megadását. Az alábbi konverziós szabályok feloldanak néhány kétértelműséget:
- Span<T>Az átalakítás , ReadOnlySpan<T>vagy egy másik
ref struct
típus jobb, mint egy nem átstrukturálási típusra való átalakítás. - A nem betűs típusra való átalakítás jobb, mint egy felülettípusra való átalakítás.
Ha egy gyűjteménykifejezést átalakítanak Span
egy vagy ReadOnlySpan
többre, a span objektum biztonságos környezete a spanban található összes elem biztonságos környezetéből származik. Részletes szabályokért tekintse meg a Gyűjtemény kifejezés specifikációját.
Gyűjteményszerkesztő
A gyűjteménykifejezések bármilyen jól működő gyűjteménytípussal működnek. A jól viselkedő gyűjtemények jellemzői a következők:
- Egy megszámlálható gyűjtemény értéke
Count
Length
ugyanazt az értéket eredményezi, mint az elemek számának számbavétele. - A névtérben lévő System.Collections.Generic típusok vélelmezhetően mellékhatásmentesek. Így a fordító optimalizálhatja azokat a forgatókönyveket, amelyekben az ilyen típusok köztes értékekként használhatók, de máskülönben nem lesznek közzétéve.
- A gyűjtemény néhány alkalmazható
.AddRange(x)
tagjának hívása ugyanazt a végső értéket eredményezi, mint az iterálásx
, és az összes számba adott érték egyenként hozzáadva a gyűjteményhez.Add
.
A .NET-futtatókörnyezet összes gyűjteménytípusa megfelelően működik.
Figyelmeztetés
Ha egy egyéni gyűjteménytípus nem megfelelően viselkedik, a gyűjteménytípus gyűjteménykifejezésekkel való használatakor a viselkedés nincs meghatározva.
A típusok egy Create()
metódus megírásával és a System.Runtime.CompilerServices.CollectionBuilderAttribute gyűjtemény típusának alkalmazásával választják a gyűjteménykifejezések támogatását, hogy jelezzék a szerkesztőmetódust. Vegyük például egy olyan alkalmazást, amely rögzített hosszúságú puffereket használ 80 karakterből. Az osztály a következő kódhoz hasonlóan nézhet ki:
public class LineBuffer : IEnumerable<char>
{
private readonly char[] _buffer = new char[80];
public LineBuffer(ReadOnlySpan<char> buffer)
{
int number = (_buffer.Length < buffer.Length) ? _buffer.Length : buffer.Length;
for (int i = 0; i < number; i++)
{
_buffer[i] = buffer[i];
}
}
public IEnumerator<char> GetEnumerator() => _buffer.AsEnumerable<char>().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _buffer.GetEnumerator();
// etc
}
Az alábbi példában látható módon gyűjteménykifejezésekkel szeretné használni:
LineBuffer line = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'];
A LineBuffer
típus implementálható IEnumerable<char>
, így a fordító elemgyűjteményként char
ismeri fel. A implementált System.Collections.Generic.IEnumerable<T> felület típusparamétere az elem típusát jelzi. Két kiegészítést kell hozzáadnia az alkalmazáshoz, hogy gyűjteménykifejezéseket rendelhessen egy LineBuffer
objektumhoz. Először létre kell hoznia egy metódust tartalmazó osztályt Create
:
internal static class LineBufferBuilder
{
internal static LineBuffer Create(ReadOnlySpan<char> values) => new LineBuffer(values);
}
A Create
metódusnak egy objektumot LineBuffer
kell visszaadnia, és egyetlen paramétert kell használnia.ReadOnlySpan<char>
A típusparaméternek ReadOnlySpan
meg kell egyeznie a gyűjtemény elemtípusával. Egy általános gyűjteményt visszaadó szerkesztőmetódus paramétere az általános ReadOnlySpan<T>
. A metódusnak elérhetőnek kell lennie, és static
.
Végül hozzá kell adnia a következőt az CollectionBuilderAttributeLineBuffer
osztálydeklarációhoz:
[CollectionBuilder(typeof(LineBufferBuilder), "Create")]
Az első paraméter a Builder osztály nevét adja meg. A második attribútum a szerkesztő metódus nevét adja meg.
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: